fwildclusterboot 0.13

Potentially Breaking Changes:

Other Changes:

Background on the Change to Seeding

Prior to the changes introduced in v0.13, boottest() will always call set.seed() or dqrng::dqset.seed() internally, regardless of whether the seed argument is specified or not (in the ladder case, it will create an internal seed by randomly drawing from a large set of integers). I consider this harmless, as setting seeds inside boottest() in this way does not affect the reproducibility of scripts run end-to-end.

However, I have learned that is generally considered bad practice to overwrite global variables without notification - for example, the authors of numpy have deprecated their np.random.seed() function for this reason.

Here is a quick example on what happens if a function “reseeds”: it affects the future chain of random draws.

fn_reseed <- function(x){set.seed(x)}

set.seed(123)
rnorm(1)
# [1] -0.5604756
fn_reseed(1)
rnorm(1)
# [1] -0.6264538

set.seed(123)
rnorm(1); rnorm(1)
# [1] -0.5604756
# [1] -0.2301775

The two ‘second’ calls to rnorm(1) are based on different global seed states.

As a result, I have decided to deprecate the seed' function argument. Random number generation must now **be** set outside ofboottest()usingset.seed()anddqrng::dqset.seed()`.

This means that bootstrap results generated via versions < 0.13 will no longer be exactly replicable under the new version, but with a sufficiently large number of bootstrap iterations, this change should not affect any of your conclusions.

fwildclusterboot 0.12.1

This is a hot-fix release which turns of tests on CRAN that fail in non-standard CRAN test environments.

fwildclusterboot 0.12

This is the first CRAN release since version 0.9. It comes with a set of new features, but also potentially breaking changes. This section summarizes all developments since version 0.9.

Potentially breaking changes:

Bug fixes and internal changes

New features and Improvements

fwildclusterboot 0.11.3

fwildclusterboot 0.11.2

fwildclusterboot 0.11.1

New bootstrap algorithms following MNW (2022)

boot_aggregate() method for Sun-Abrahams Event Studies

A boot_aggregate() method to supports the aggregation of coefficients in staggered difference-in-differences following the methods by Sun & Abraham (2021, Journal of Econometrics) in combination with the sunab() function from fixesthas been added. Essentially, boot_aggregate() is a copy of aggregate.fixest: the only difference is that inference is powered by a wild bootstrap.

Other syntax changes, potentially breaking!

boottest(
  lm_fit, 
  param = ~treatment, 
  clustid = ~group_id1,
  B = 9999, 
  impose_null = TRUE,
  engine = "R", 
  bootstrap_type = "11"
)

To run everything through WildBootTests.jl, you would have to specify

boottest(
  lm_fit, 
  param = ~treatment, 
  clustid = ~group_id1,
  B = 9999, 
  impose_null = TRUE,
  engine = "WildBootTests.jl", 
  bootstrap_type = "11"
)

fwildclusterboot 0.11

You can run one of the ‘new’ variants - e.g. the “WCR13”, by specifying the bootstrap_type function argument accordingly:

boottest(
  lm_fit, 
  param = ~treatment, 
  clustid = ~group_id1,
  B = 9999, 
  impose_null = TRUE,
  engine = "R", 
  bootstrap_type = "31"
)

fwildclusterboot 0.10

fwildclusterboot 0.9

library(fwildclusterboot)
library(fixest)

data(voters)
feols_fit <- feols(proposition_vote ~ i(treatment, ideology1) ,
    data = voters
)
boot1 <- boottest(feols_fit,
    B = 9999,
    param = "treatment::0:ideology1",
    clustid = "group_id1"
)

feols_fits <- fixest::feols(proposition_vote ~ treatment | sw(Q1_immigration, Q2_defense), data = voters)
res <- lapply(feols_fits, \(x) boottest(x, B = 999, param = "treatment", clustid = "group_id1"))  

voters$split <- sample(1:2, nrow(voters), TRUE)
feols_fits <- fixest::feols(proposition_vote ~ treatment, split = ~split, data = voters)

res <- lapply(feols_fits, \(x) boottest(x, B = 999, param = "treatment", clustid = "group_id1"))  

Some formula sugar still leads to errors, e.g. 

feols_fit2 <- feols(proposition_vote ~ treatment | Q1_immigration^Q2_defense,
    data = voters
)

boot1 <- boottest(feols_fit2,
    B = 9999,
    param = "treatment",
    clustid = "group_id1"
)
data(voters)
feols_fit <- feols(proposition_vote ~ treatment ,
    data = voters
)
boot <- boottest(feols_fit,
    B = 9999,
    param = ~ treatment,
    clustid = ~ group_id1
)

fwildclusterboot 0.8

Two new bootstrap algorithms: ‘WildBootTests.jl’ and ‘R-lean’

boot_algo = ‘WildBootTests.jl’

# load data set voters included in fwildclusterboot
data(voters)
# estimate the regression model via lm
lm_fit <- lm(proposition_vote ~ treatment + ideology1 + log_income + Q1_immigration , data = voters)
boot_lm <- boottest(
  lm_fit, 
  clustid = "group_id1", 
  param = "treatment", 
  B = 9999, 
  boot_algo = "WildBootTests.jl"
)
library(ivreg)
data("SchoolingReturns", package = "ivreg")
# drop all NA values from SchoolingReturns
SchoolingReturns <- na.omit(SchoolingReturns)
ivreg_fit <- ivreg(log(wage) ~ education + age + ethnicity + smsa + south + parents14 |
                           nearcollege + age  + ethnicity + smsa + south + parents14, data = SchoolingReturns)

boot_ivreg <- boottest(
  object = ivreg_fit,
  B = 999,
  param = "education",
  clustid = "kww",
  type = "mammen",
  impose_null = TRUE
)
generics::tidy(boot_ivreg)
#              term  estimate statistic   p.value    conf.low conf.high
# 1 1*education = 0 0.0638822  1.043969 0.2482482 -0.03152655 0.2128746

boot_algo = ‘R-lean’

A key limitation of the vectorized ‘fast’ cluster bootstrap algorithm as implemented in fwildclusterboot is that it is very memory-demanding. For ‘larger’ problems, running boottest() might lead to out-of-memory errors. To offer an alternative, boottest() now ships a ‘new’ rcpp- and loop-based implementation of the wild cluster bootstrap (the ‘wild2’ algorithm in Roodman et al).

boot_lm <- boottest(
  lm_fit, 
  clustid = "group_id1", 
  param = "treatment", 
  B = 9999, 
  boot_algo = "R-lean"
)

Heteroskeadstic Wild Bootstrap

It is now possible to run boottest() without specifying a clustid function argument. In this case, boottest() runs a heteroskedasticity-robust wild bootstrap (HC1), which is implemented in c++.

boot_hc1 <- boottest(lm_fit, param = "treatment", B = 9999)
summary(boot_hc1)

boottest() function argument beta0 deprecated

For consistency with WildBootTests.jl, the boottest() function argument beta0 is now replaced by a new function argument, r.

Frühjahrsputz

I have spent some time to clean up fwildclusterboot's internals, which should now hopefully be more readable and easier to maintain.

Testing

fwildclusterboot is now pre-dominantly tested against WildBootTests.jl. Tests that depend on Julia are by default not run on CRAN, but are regularly run on Mac, Windows and Linux via github actions.

fwildclusterboot 0.7

fwildclusterboot 0.6

fwildclusterboot 0.5.1

fwildclusterboot 0.5

fwilclusterboot 0.4

fwildclusterboot 0.3.7

fwildclusterboot 0.3.6

fwildclusterboot 0.3.5

fwildclusterboot 0.3.4

fwildclusterboot 0.3.3

fwildclusterboot 0.3.2

fwildclusterboot 0.3.1

fwildclusterboot 0.3.0

fwildclusterboot 0.2.0

Add support for