I want to use the boot
package to calculate bootstrap confidence intervals for the mean. Sure, I could do this by inverting a t-test, but I want to see what happens when I use a bootstrap approach.
I do this by simulating some data and then passing the data to the boot::boot
function in R, with the statistic
set to the usual mean
function.
library(boot)
set.seed(2024)
N <- 100 # Sample size
B <- 999 # Number of bootstrap samples drawn
# Simulate some data, distributed N(0, 1)
#
x <- rnorm(N, 0, 1)
# Try to bootstrap with just "mean" as the statistic
#
boot::boot(x, mean, R = B)
# Oops, that failed!
This code fails.
From the documentation, ?boot::boot
.
A function which when applied to data returns a vector containing the statistic(s) of interest. When
sim = "parametric"
, the first argument tostatistic
must be the data. For each replicate a simulated dataset returned byran.gen
will be passed. In all other casesstatistic
must take at least two arguments. The first argument passed will always be the original data. The second will be a vector of indices, frequencies or weights which define the bootstrap sample. Further, if predictions are required, then a third argument is required which would be a vector of the random indices used to generate the bootstrap predictions. Any further arguments can be passed tostatistic
through the...
argument.
The statistic
argument to boot::boot
is a function that has an index argument, so instead of passing mean <- function(x){n <- length(x); return(sum(x)/n)}
, I must pass something more like mean_boot <- function(x, i){y <- x[i]; return(mean(y))}
. Indeed, this works.
# Define a new function to calculate means within boot::boot
#
mean_boot <- function(x, i){
y <- x[i] # Select values with index i
return(mean(y))
}
# Try the bootstrap again
#
result <- boot::boot(x, mean_boot, R = B)
# Calculate confidence intervals
#
boot::boot.ci(result)
#
# Bootstap confidence intervals calculated here are:
# Normal: (-0.2758, 0.1167)
# Basic: (-0.2702, 0.1249)
# Percentile: (-0.2948, 0.1003)
# BCa: (-0.2911, 0.1068)
# Inverting a t-test gives a 95% confidence interval of
# (-0.2878159, 0.1179510). With all of the 95% bootstrap intervals being quite
# close to ]than this, it seems that mean_boot is the correct syntax to
# calculate the usual sample mean within boot::boot.
#
t.test(x)
Why should boot::boot
be written this way, requiring the statistic
function to use an index argument instead of just performing the resampling within boot::boot
and passing the resampled data into whatever is passed as the statistic
? Does this allow for easier syntax when the statistic being calculated is more complex than a sample mean, perhaps something from a GLM or machine learning model? Does it allow for easier parallelization of the bootstrapping when the complexity is great enough to require that (more than 100
observations, more than calculating a sample mean)? Something related to running a double bootstrap?
I have always found this to make work harder when I use the boot
package. Are there situations where it makes work easier?
boot()
. Stuff like this is very hard to get out of software once it has been released... $\endgroup$boot
developer would be appreciated, but I think someone who has been in a situation where thisi
argument made it easier to use the package could describe that for a totally acceptable answer. $\endgroup$boot::boot
and forget thei
in thestatistic
argument? $//$ I would be disappointed as a statistician but rather content as a human if all this question generates are comments along the lines of, "I hate this." $\endgroup$boot
has no way of knowing how it should subsample whatever object you provide it with. $\endgroup$