diff --git a/R/statistical_tests_and_estimates.R b/R/statistical_tests_and_estimates.R index 3f814f6..ddb7bf0 100644 --- a/R/statistical_tests_and_estimates.R +++ b/R/statistical_tests_and_estimates.R @@ -461,14 +461,32 @@ binom_ci <- function(x, methods = 'wilson', ...){ - .check_response_input(x) .check_numeric_input(conf.level, lower_bound = 0, upper_bound = 1 - 1E-12, scalar = TRUE, whole_num = FALSE, allow_NA = FALSE) - x <- stats::na.omit(x) + # Check input type/length (errors for empty or wrong type) + # but handle all-NA case with warning instead of error + if (length(dim(x)) > 1) stop('"x" must be a vector (one-dimensional object)') + if (length(x) == 0) stop('"x" length must be > 0') + + x_nona <- x[!is.na(x)] + + if (!is.logical(x) & length(x_nona) > 0 & !all(x_nona %in% c(0, 1))) + stop('"x" must be a numeric vector containing only 0/1 values or a logical vector containing only T/F values') + + if (length(x_nona) == 0) { + warning('"x" has no non-NA values. Returning NA results.') + na_result <- binom::binom.confint(x = 0, n = 0, + conf.level = conf.level, + methods = methods) + na_result$mean <- NA_real_ + na_result$lower <- NA_real_ + na_result$upper <- NA_real_ + return(na_result) + } - npos <- sum(x); - n <- length(x); + npos <- sum(x_nona); + n <- length(x_nona); binom::binom.confint(x = npos, n = n, diff --git a/tests/testthat/test_statistical_tests_and_estimates.R b/tests/testthat/test_statistical_tests_and_estimates.R index 8f3dde2..d6df545 100644 --- a/tests/testthat/test_statistical_tests_and_estimates.R +++ b/tests/testthat/test_statistical_tests_and_estimates.R @@ -493,14 +493,20 @@ test_that("test-wilson_ci", { test_that("test-binom_ci", { # check x - expect_error(binom_ci(c(NA, NA, NA)), '"x" must have at least one non-NA value') expect_error(binom_ci(c()), '"x" length must be > 0') - expect_error(binom_ci(c(NA, NA, NA)), '"x" must have at least one non-NA value') expect_error(binom_ci(x = c("F", "T", "F", "T")), '"x" must be a numeric vector containing only 0/1 values or a logical vector containing only T/F values') expect_error(binom_ci(x = factor(c("F", "T", "F", "T"))), '"x" must be a numeric vector containing only 0/1 values or a logical vector containing only T/F values') + # all-NA input should warn and return NAs (issue #105) + expect_warning(result <- binom_ci(c(NA, NA, NA)), 'no non-NA values') + expect_true(all(is.na(result$mean))) + expect_true(all(is.na(result$lower))) + expect_true(all(is.na(result$upper))) + expect_equal(result$x, 0) + expect_equal(result$n, 0) + # binom_ci() should match binom::binom.confint() x <- c(1, 1, 1, 0, 0) expect_equal(binom_ci(x), binom::binom.wilson(3, 5))