# Confidence intervals of bounded variable

Given 1000 observations that come from a distribution that is bounded between 0 and 1. How do you calculate correct 95% Confidence intervals when dealing with a bounded distribution?

set.seed(10)
data = runif(1000, min=0, max=1)
mean(data)
mean(data) + 1.96*sd(data)/sqrt(length(data)) # usual CIs
mean(data) - 1.96*sd(data)/sqrt(length(data)) # usual CIs

• The wanted CI is not on the variable but on its unknown expectation as the code suggests.
– Yves
Commented Dec 2, 2016 at 16:58
• If you are looking for confidence interval based on hypothesis testing, then generally you need to have a family of distribution in mind from where the sample is drawn. Then you can construct confidence interval on the unknown parameters of the distribution. The use of 1.96, as you have done, is for normal distribution family - which would not be the case for you if support is bounded. For possible distributions, see here. Commented Oct 25, 2019 at 4:46

This is a later answer but perhaps may be useful to someone. I have an R package on github (mlisi) with a set of convenient functions, including one that calculate boostrapped confidence intervals using the bias-corrected and accelerated method (Efron, 1987).

> set.seed(10)
> data = runif(1000, min=0, max=1)
> library(mlisi)
> bootMeanCI(data, nsim=10^4)
2.797862%  97.7708%
0.4874827 0.5240060


Although the BCa method is the default, you can also use the percentile method by setting the argument 'method'

> bootMeanCI(data, nsim=10^4, method="percentile")
2.5%     97.5%
0.4871504 0.5236511


You can install the package from github using devtools

library(devtools)
install_github("mattelisi/mlisi")


Your best best here would be to use bootstrapped CIs instead of parametric CIs. Here is a contrived example to show when parametric CIs would give impossible results but bootstrap CIs do not:

> # Simulate Bounded Data
> set.seed(10)
> n <- 5
> data <-  rnorm(n, mean = 1, sd = 0.5)
> data[data > 1] <- 1
>
> # Sample Mean
> est <- mean(data)
>
> # Parametric CI
> p_lci <- mean(data) - 1.96 * sd(data) / sqrt(n)
> p_uci <- mean(data) + 1.96 * sd(data) / sqrt(n)
>
> # Bootstrapped CI
> nboot <- 2000
> resample_dist <- rep(NA, length = nboot)
> for (i in 1:nboot) {
+   resample_i <- sample(data, size = n, replace = TRUE)
+   resample_dist[[i]] <- mean(resample_i)
+ }
> b_lci <- quantile(resample_dist, probs = 0.025)
> b_uci <- quantile(resample_dist, probs = 0.975)
>
> # Display Results
> sprintf("Parametric: %.3f [%.3f, %.3f]", est, p_lci, p_uci)
#> [1] "Parametric: 0.785 [0.530, 1.039]"
> sprintf("Bootstrapped: %.3f [%.3f, %.3f]", est, b_lci, b_uci)
#> [1] "Bootstrapped: 0.785 [0.529, 0.982]"