Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianGoueguel committed Apr 5, 2024
1 parent f50e6b5 commit 50975cf
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 21 deletions.
6 changes: 5 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ Roxygen: list(markdown = TRUE)
URL: https://christiangoueguel.github.io/ConfidenceEllipse/
Suggests:
knitr,
rmarkdown
rmarkdown,
spelling,
testthat (>= 3.0.0)
VignetteBuilder: knitr
Depends:
R (>= 2.10)
Language: en-US
Config/testthat/edition: 3
17 changes: 7 additions & 10 deletions R/confidence_ellipse.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
#' @param conf_level The confidence level for the ellipse (0.95 by default).
#' @return A data frame of the coordinates points of the ellipse.
#' @export confidence_ellipse

confidence_ellipse <- function(.data, x, y, .group_by = NULL, conf_level = 0.95) {

if (missing(.data)) {
stop("Missing 'data' argument.")
}
Expand All @@ -20,24 +18,23 @@ confidence_ellipse <- function(.data, x, y, .group_by = NULL, conf_level = 0.95)
if (!is.numeric(conf_level)) {
stop("'conf_level' must be numeric.")
}
if (conf_level < 0 && conf_level > 1) {
if (conf_level < 0 || conf_level > 1) {
stop("'conf_level' must be between 0 and 1.")
}

transform_data <- function(.x, conf_level) {
mean_vec <- colMeans(.x)
cov_mat <- stats::cov(.x)
if (any(is.na(cov_mat))) {
stop("warning: the covariance matrix is singular")
cov_matrix <- stats::cov(.x)
if (any(is.na(cov_matrix))) {
stop("Covariance matrix contains NA values.")
}
else {
eig <- eigen(cov_mat)
eig <- eigen(cov_matrix)
theta <- (2 * pi * seq(0, 360, 1)) / 360
X <- sqrt(eig$values[1] * stats::qchisq(conf_level, 2)) * cos(theta)
Y <- sqrt(eig$values[2] * stats::qchisq(conf_level, 2)) * sin(theta)
R <- cbind(X, Y) %*% t(eig$vectors)
res <- R + matrix(rep(t(mean_vec), 361), ncol = ncol(t(mean_vec)), byrow = TRUE)
return(res)
result <- R + matrix(rep(t(mean_vec), 361), ncol = ncol(t(mean_vec)), byrow = TRUE)
return(result)
}
}
if (rlang::quo_is_null(rlang::enquo(.group_by))) {
Expand Down
18 changes: 8 additions & 10 deletions R/confidence_ellipsoid.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
#' @param conf_level The confidence level for the ellipse (0.95 by default).
#' @return A data frame of the coordinates points of the ellipse.
#' @export confidence_ellipsoid

confidence_ellipsoid <- function(.data, x, y, z, .group_by = NULL, conf_level = 0.95) {

if (missing(.data)) {
stop("Missing 'data' argument.")
}
Expand All @@ -23,23 +21,23 @@ confidence_ellipsoid <- function(.data, x, y, z, .group_by = NULL, conf_level =
if (conf_level < 0 || conf_level > 1) {
stop("'conf_level' must be between 0 and 1.")
}

transform_data <- function(.x, conf_level) {
mean_vec <- colMeans(.x)
cov_mat <- stats::cov(.x)
if (any(is.na(cov_mat))) {
stop("Warning: The covariance matrix is singular.")
} else {
eig <- eigen(cov_mat)
cov_matrix <- stats::cov(.x)
if (any(is.na(cov_matrix))) {
stop("Covariance matrix contains NA values.")
}
else {
eig <- eigen(cov_matrix)
theta <- seq(0, 2 * pi, length.out = 50)
phi <- seq(0, pi, length.out = 50)
grid <- expand.grid(Theta = theta, Phi = phi)
X <- sqrt(eig$values[1] * stats::qchisq(conf_level, 3)) * sin(grid$Phi) * cos(grid$Theta)
Y <- sqrt(eig$values[2] * stats::qchisq(conf_level, 3)) * sin(grid$Phi) * sin(grid$Theta)
Z <- sqrt(eig$values[3] * stats::qchisq(conf_level, 3)) * cos(grid$Phi)
R <- cbind(X, Y, Z) %*% t(eig$vectors)
res <- R + matrix(rep(mean_vec, nrow(R)), ncol = length(mean_vec), byrow = TRUE)
return(res)
result <- R + matrix(rep(mean_vec, nrow(R)), ncol = length(mean_vec), byrow = TRUE)
return(result)
}
}
if (rlang::quo_is_null(rlang::enquo(.group_by))) {
Expand Down
14 changes: 14 additions & 0 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Acta
CMD
De
Janssen
Lifecycle
Microchim
Raedt
Schalm
Trivariate
Veeckman
magrittr
th
tibble
trivariate
3 changes: 3 additions & 0 deletions tests/spelling.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if(requireNamespace('spelling', quietly = TRUE))
spelling::spell_check_test(vignettes = TRUE, error = FALSE,
skip_on_cran = TRUE)
12 changes: 12 additions & 0 deletions tests/testthat.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file is part of the standard setup for testthat.
# It is recommended that you do not modify it.
#
# Where should you do additional test configuration?
# Learn more about the roles of various files in:
# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
# * https://testthat.r-lib.org/articles/special-files.html

library(testthat)
library(ConfidenceEllipse)

test_check("ConfidenceEllipse")
57 changes: 57 additions & 0 deletions tests/testthat/test-confidence_ellipse.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
library(tibble)
data("glass", package = "ConfidenceEllipse")
# Test cases covered:
# confidence_ellipse function stops when no data is provided.
# confidence_ellipse function stops when input data is not a data frame or tibble.
# confidence_ellipse function stops when the conf_level is not numeric.
# confidence_ellipse function stops when the conf_level is not between 0 and 1.
# confidence_ellipse function returns a tibble.
# confidence_ellipse function works correctly with a simple example.
# confidence_ellipse function works correctly with a grouping factor.
# confidence_ellipse function stops when the covariance matrix contains NA's.
test_that("function stops with no data", {
expect_error(confidence_ellipse(), "Missing 'data' argument.")
})
test_that("function stops with non df or tbl input", {
expect_error(confidence_ellipse(.data = 123), "Input 'data' must be a data frame or tibble.")
})
test_that("function stops with non-numeric conf_level", {
expect_error(
confidence_ellipse(
.data = glass,
x = BaO,
y = PbO,
conf_level = "high"),
"'conf_level' must be numeric.")
})
test_that("function stops with invalid conf_level", {
expect_error(
confidence_ellipsoid(
.data = glass,
x = BaO,
y = PbO,
conf_level = 37),
"'conf_level' must be between 0 and 1.")
})
test_that("function returns a data frame or tibble", {
result <- confidence_ellipse(glass, BaO, PbO)
expect_true(is_tibble(result))
})
test_that("function works with simple example", {
df <- data.frame(x = 1:10, y = 11:20)
result <- confidence_ellipse(df, x, y)
expect_true(is_tibble(result))
})
test_that("function works with grouping factor", {
result <- confidence_ellipse(
.data = glass,
x = BaO,
y = PbO,
.group_by = glassType)
expect_true(is_tibble(result))
})
test_that("function stops with NA's in covariance matrix", {
df <- data.frame(x = 1:10, y = c(11, 2, 4, NA, 6, 3, 1, NA, NA, 10))
expect_error(confidence_ellipse(df, x, y), "Covariance matrix contains NA values.")
})

63 changes: 63 additions & 0 deletions tests/testthat/test-confidence_ellipsoid.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
library(tibble)
# Test cases covered:
# confidence_ellipsoid function stops when no data is provided.
# confidence_ellipsoid function stops when input data is not a data frame or tibble.
# confidence_ellipsoid function stops when the conf_level is not numeric.
# confidence_ellipsoid function stops when the conf_level is not between 0 and 1.
# confidence_ellipsoid function returns a tibble.
# confidence_ellipsoid function works correctly with a simple example.
# confidence_ellipsoid function works correctly with a grouping factor.
# confidence_ellipsoid function stops when the covariance matrix contains NA's.
test_that("function stops with no data", {
expect_error(confidence_ellipsoid(), "Missing 'data' argument.")
})
test_that("function stops with non df or tbl input", {
expect_error(confidence_ellipsoid(.data = 123), "Input 'data' must be a data frame or tibble.")
})
test_that("function stops with non-numeric conf_level", {
expect_error(
confidence_ellipsoid(
.data = glass,
x = BaO,
y = PbO,
z = Na2O,
conf_level = "high"),
"'conf_level' must be numeric.")
})
test_that("function stops with invalid conf_level", {
expect_error(
confidence_ellipsoid(
.data = glass,
x = BaO,
y = PbO,
z = Na2O,
conf_level = 37),
"'conf_level' must be between 0 and 1.")
})
test_that("function returns a data frame or tibble", {
result <- confidence_ellipsoid(glass, BaO, PbO, Na2O)
expect_true(is_tibble(result))
})
test_that("function works with simple example", {
df <- data.frame(x = 1:10, y = 11:20, z = 11:20)
result <- confidence_ellipsoid(df, x, y, z)
expect_true(is_tibble(result))
})
test_that("function works with grouping factor", {
result <- confidence_ellipsoid(
.data = glass,
x = BaO,
y = PbO,
z = Na2O,
.group_by = glassType)
expect_true(is_tibble(result))
})
test_that("function stops with NA's in covariance matrix", {
df <- data.frame(
x = 1:10,
y = c(11, 2, 4, NA, 6, 3, 1, NA, NA, 10),
z = 11:20)
expect_error(confidence_ellipsoid(df, x, y, z), "Covariance matrix contains NA values.")
})


0 comments on commit 50975cf

Please sign in to comment.