Nothing
# Function to find sample size 'n' for exact confidence interval given the proportion estimate and confidence interval.
# zexactn(est = 0.3, low = 0.2, upp = 0.4)
zexactn <- function(est, low, upp, conf.level = 0.95) {
# Input validation:
if (est <= 0 || est >= 1) stop("Argument est must be between 0 and 1")
if (low >= upp) stop("Argument low must be less than upp")
if (low < 0 || upp > 1) stop("Confidence limits must be between 0 and 1")
if (est < low || est > upp) stop("Argument est must be within the confidence interval")
# Objective function to minimise:
objective <- function(n_real) {
n <- round(n_real)
if (n < 1) return(Inf)
a <- round(n * est)
# Calculate CI using your original logic
alpha <- 1 - conf.level
alpha2 <- alpha / 2
if (a == 0) {
rlow <- 0
rupp <- 1 - qbeta(alpha2, n, 1)
} else if (a == n) {
rlow <- 1 - qbeta(1 - alpha2, 1, n)
rupp <- 1
} else {
rlow <- 1 - qbeta(1 - alpha2, n + 1 - a, a)
rupp <- 1 - qbeta(alpha2, n - a, a + 1)
}
# Return squared distance from target CI:
return((rlow - low)^2 + (rupp - upp)^2)
}
# Optimise to find best n:
result <- stats::optimize(objective, interval = c(1,10000))
best.n <- round(result$minimum)
best.a <- round(best.n * est)
# Calculate actual CI for the result:
alpha <- 1 - conf.level
alpha2 <- alpha / 2
if (best.a == 0) {
rlow <- 0
rupp <- 1 - qbeta(alpha2, best.n, 1)
} else if (best.a == best.n) {
rlow <- 1 - qbeta(1 - alpha2, 1, best.n)
rupp <- 1
} else {
rlow <- 1 - qbeta(1 - alpha2, best.n + 1 - best.a, best.a)
rupp <- 1 - qbeta(alpha2, best.n - best.a, best.a + 1)
}
return(list(
a = best.a,
n = best.n,
actual = c(est = est, low = low, upp = upp),
estimate = c(est = best.a / best.n, low = rlow, upp = rupp),
objective = result$objective
))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.