Skip to main content
Post Closed as "Not suitable for this site" by Nick Cox, PBulls, User1865345
Became Hot Network Question
edited title
Link
Dave
  • 67.2k
  • 7
  • 105
  • 305

Why does the `boot` R package require the `i` argument? When does it make the package easier to use instead of harder?

Source Link
Dave
  • 67.2k
  • 7
  • 105
  • 305

Why does the `boot` R package require the `i` argument?

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 to statistic must be the data. For each replicate a simulated dataset returned by ran.gen will be passed. In all other cases statistic 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 to statistic 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?