4
$\begingroup$

I am interested in finding the interval estimate of the mean of my response variable when the predictor variable is equal to a certain value, that is $E[Y|X=x]$. The point estimate for this statistic I am bootstrapping is $\hat{\beta_0} + \hat{\beta_1}x$.

However, I am having trouble calculating this statistic in the bootstrap replication. Here is what I have so far:

# load the libraries
library(purrr)
library(caret)

# set the seed 
set.seed(872)

# load the data
boston = tibble::as_tibble(MASS::Boston)

# store the indices for use in 400 bootstrap resamples
index_resampling = createResample(boston$medv, times = 400)

# create a bootstrap resampling function
create_boot_resampling = function(data, idx) {
  data[idx]
}

# fit the model
mod = lm(medv ~ rm, data = boston)

# calculate the bootstrap resamples
bootstrap_resample = map(index_resampling, ~create_boot_resampling(data = boston$medv, idx = .x))

# calculate the bootstrap replicates
bootstrap_replicate = unname(map_dbl(bootstrap_resample, ~predict(lm(.x ~ rm, data = boston), data.frame(rm = 4.929))))

# find the 90% confidence interval
quantile(bootstrap_replicate, probs = c(0.05, 0.950))

The medv is the response variable, and the rm is the predictor variable from the Boston dataset. I would like to find the point estimates of medv when rm is equal to 4.929, that is $\hat{\beta_0} + \hat{\beta_1} *$ 4.929. The code runs fine, but the confidence interval it outputs is incorrect. I have a feeling my error lies in the predict function used in the bootstrap replicate code, but I am unsure how to get the correct answer. Any hints or advice would be helpful!

$\endgroup$
3
  • 5
    $\begingroup$ I don't speak tidyverse. What's wrong with good old package boot? library(boot); set.seed(872); myboot <- boot(MASS::Boston, function(DF, i) { predict(lm(medv ~ rm, data = DF[i,]), newdata = data.frame(rm = 4.929)) }, R = 400); boot.ci(myboot, conf = 0.9, type = "basic") $\endgroup$
    – Roland
    Oct 14, 2020 at 6:13
  • $\begingroup$ I don't speak tidyverse as well. To the uninitiated your definition of bootstrap_replicate as map_dbl(bootstrap_resample, ~predict(lm(.x ~ rm, data = boston) seems to take the y-values from your bootstrap samples but the rm values from the original undbootstrapped boston. May that be the problem? Also: "output is incorrect" is a very vague error description. In future questions you should try to give mor details on how to spot that there is a problem. $\endgroup$
    – Bernhard
    Oct 14, 2020 at 7:04
  • $\begingroup$ Computation w/o any additional package leads to the same result as @Roland 's set.seed(872); predict_medv <- function(rows){ regr <- lm(medv ~ rm, data = MASS::Boston[rows,]); predict(regr, newdata = data.frame(rm = 4.929)) }; bootstrapped <- replicate(4000, predict_medv(rows = sample(nrow(MASS::Boston), replace = TRUE))); quantile(bootstrapped, c(.05, .95)) $\endgroup$
    – Bernhard
    Oct 14, 2020 at 7:47

1 Answer 1

8
$\begingroup$

As already explained in my first comment I believe your problem is that you bootstrapped medv but not rm. I tried to change your code to work appropriately by conserving as much of your code as possible. Even though I myself would not have defined boston as a tibble copy of MASS::Boston when nothing is done to boston that is tibble specific and I myself would not have defined a create_boot_resampling function that does so little.

I hope you learn most from changes in your old code, otherwise Roland has posted a good solution as the first comment to the question.

set.seed(872)

# load the data
boston = tibble::as_tibble(MASS::Boston)

# store the indices for use in 400 bootstrap resamples
index_resampling = createResample(boston$medv, times = 400)

# create a bootstrap resampling function
create_boot_resampling = function(data, idx) {
  data[idx]
}

# fit the model
mod = lm(medv ~ rm, data = boston)

# calculate the bootstrap resamples
#bootstrap_resample = map(index_resampling, ~create_boot_resampling(data = boston$medv, idx = .x))
# instead: make a list of data.frames each containing bootstrap samples of medv and rm 
bootstrap_rs <- lapply(index_resampling, function(is) boston[is, c("medv", "rm")])

# calculate the bootstrap replicates
#bootstrap_replicate = unname(map_dbl(bootstrap_resample, ~predict(lm(.x ~ rm, data = boston), data.frame(rm = 4.929))))
bootstrap_replicate <- sapply(1:length(bootstrap_rs), 
                              function(i) predict(lm(medv ~ rm, bootstrap_rs[[i]]), data.frame(rm = 4.929)))

# find the 90% confidence interval
quantile(bootstrap_replicate, probs = c(0.05, 0.950))

# always look at your data to confirm everything worked fine
hist(bootstrap_replicate, freq = FALSE)
lines(density(bootstrap_replicate), lwd = 2)
rug(bootstrap_replicate)

This gives the same result as Rolands and my comment code so we can assume this is correct. I apologize for using lapply and sapply which are standard R function when obviously you prefer purrr but I assume there will be an easy way to translate that to purrr.

$\endgroup$
2
  • $\begingroup$ This works perfectly! Your changes helped me understand where I went wrong in my code. I was able to resolve the problem using the tidyverse code I had originally rather than using lapply and sapply, but it nonetheless resulted in the same answer. Thank you for taking the time to help me with this - it's my first time learning about bootstrapping, and I spent way too much time on this problem. I agree using the boot package or using the standard R functions is probably easier than using tidyverse, but this is the way my professor taught us :-) $\endgroup$
    – user222266
    Oct 14, 2020 at 8:28
  • $\begingroup$ @Aspire The tidyverse started with Hadley Wickham and you can hear his opinion on mixing tidiverse with other idioms and other packages here: youtu.be/vYwXMnC03I4?t=2137 Among other things he said (a year ago) "I do not believe that most data analyses could be accomplished by the tidyverse alone. There has never been the intent to be everything". $\endgroup$
    – Bernhard
    Oct 14, 2020 at 9:16

Your Answer

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

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