3
$\begingroup$

I am going through an online course on Data Analysis and Statistical Inference, and I am having trouble understanding the Bootstrapping method. I am asking the question here, as the course is not very well developed.

In the course, we repeatedly take samples from a variable "weight gained" (973 clean data points), but the size of each sample is the size of the length of the variable (i.e. taking all 973 data points each time), we calculate the mean for each sample, and then 'replace' the sample for the next batch.

So I guess my question is, why would the mean of each sample be different, if I am taking all the data points each time? I must be missing something here.

The R code we are using is:

# Initialize the 'boot_means' object:
boot_means = rep(NA, 100)

# Insert your for loop:
for(i in 1:100){
  boot_sample = sample(gained_clean, n, replace = TRUE)
  boot_means[i] = mean(boot_sample)
}

# Make a histogram of 'boot_means':
hist(boot_means)
$\endgroup$
1
  • 4
    $\begingroup$ Sampling is with replacement. If your data are $\{1,2,3\}$ one psuedo-sample might be {1,2,1}, the next might be {3,1,1} and the one after that could be {2,2,2}. The probability (with no ties in the data) of getting the sample back with large n is very small $\:$ Possible duplicate here? $\endgroup$
    – Glen_b
    Feb 6, 2015 at 5:01

1 Answer 1

3
$\begingroup$

(Note that you can make a reproducible example by setting the seed and generating some data. This facilitates people working on your problem and helping them help you, because both can reproduce the same results.)

Did you try it? Did you notice that you actually get back a vector of identical means? Let's try it here:

set.seed(7793)
n = 973
gained_clean = rnorm(n, mean=0, sd=1)
summary(gained_clean)
#     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
# -3.79300 -0.69380 -0.03424 -0.05384  0.59740  3.34300 
confint(lm(gained_clean~1), level=.90)
#                    5 %         95 %
# (Intercept) -0.1066353 -0.001050521

boot_means = rep(NA, 100)

# Insert your for loop:
for(i in 1:100){
  boot_sample = sample(gained_clean, n, replace = TRUE)
  boot_means[i] = mean(boot_sample)
}
summary(boot_means)
#      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
# -0.124800 -0.070680 -0.052570 -0.054840 -0.033300  0.006434 
sort(boot_means)[5]   # [1] -0.1121571
sort(boot_means)[95]  # [1] -0.009469124

enter image description here

The first thing to notice is that the population from which the data were generated has a mean of 0. However, the realized data have a mean of -0.05384. Nonetheless, because this is a simulation, we pretend we don't know the true data generating process and take our sample as a model of the population itself. The bootstrap gives us a sense of what the sampling distribution of the mean from our sample-as-population would look like. Notice that the mean of that sampling distribution (-0.054840) is centered on the sample mean. Furthermore, note that the 90% confidence interval derived from the bootstrapped sampling distribution is [-0.112, -0.009]. In this case, it doesn't cover the true mean, but in the long run it will 90% of the time and is quite similar to the analytically derived confidence interval [-0.107, -0.001].

So (getting to your explicit question), how did this work? The key is that bootstrapping (and the R function ?sample(x, size, replace=TRUE)) is not returning your exact sample each time. Instead, it returns a sample drawn with replacement. Let's re-run the above code (especially setting the seed again for reproducibility), but this time taking a look at the first few data:

...  # some code skipped
head(gained_clean)
# [1]  0.12336275  0.42359922 -0.09915415 -0.05301904  0.51948019  0.20804275
boot_samples_matrix = matrix(rep(NA, n*5), nrow=n)
for(i in 1:5){
  boot_samples_matrix[,i] = sample(gained_clean, n, replace = TRUE)
}
cbind(head(gained_clean), head(boot_samples_matrix))
#             [,1]       [,2]       [,3]        [,4]       [,5]       [,6]
# [1,]  0.12336275  0.6149658 -0.3477429  0.04203624  0.4091023 -0.4760131
# [2,]  0.42359922 -0.2879273  0.7248926 -0.83440292 -0.3450141 -0.3688194
# [3,] -0.09915415  0.2208385  0.4497207 -0.45045587  0.1422502 -0.3079226
# [4,] -0.05301904 -0.9771884 -1.0765040  0.50582315 -0.9665563  1.9123963
# [5,]  0.51948019 -0.4365715 -0.9910226 -0.23829268  0.2485701 -1.7783639
# [6,]  0.20804275  1.6725675  1.1873863 -0.22584317 -0.2014681  0.3144087

Now we can see that they aren't the same each time at all. Of course, these could have been just shuffled, so let's check for that:

sum(duplicated(gained_clean))  # [1] 0
apply(boot_samples_matrix, MARGIN=2, FUN=function(x){ sum(duplicated(x)) })
# [1] 343 370 343 366 362

There were no duplicated data in the original vector gained_clean, but there were about 357, on average, duplicated data in each boot sample.

$\endgroup$
2
  • $\begingroup$ Thanks for the great answer. Makes perfect sense now. Still a newbie in R so didn't know about seeds. $\endgroup$
    – Terrence J
    Feb 6, 2015 at 5:37
  • $\begingroup$ That's OK, half the point of my answer was to show you how to play with R to figure these things out. $\endgroup$ Feb 6, 2015 at 5:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.