Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch to dqrng::dqrrademacher #134; bump version to 0.15 #143

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions CRAN-SUBMISSION
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
Version: 0.14.0
Date: 2023-07-09 19:55:48 UTC
SHA:
431829b4d99cd13f0652e71483b3ce8e87cb5b58
Version: 0.15.0
Date: 2023-09-16 18:11:27 UTC
SHA: 47b7f6ad8815300458eca67327699ea865a8c878
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: fwildclusterboot
Title: Fast Wild Cluster Bootstrap Inference for Linear Models
Version: 0.14.3
Version: 0.15.0
Authors@R: c(
person("Alexander", "Fischer", , "[email protected]", role = c("aut", "cre")),
person("David", "Roodman", role = "aut"),
Expand Down
3 changes: 2 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ export(glance)
export(mboottest)
export(pval)
export(setBoottest_engine)
export(setBoottest_nthreads)
export(teststat)
export(tidy)
importFrom(JuliaConnectoR,juliaEval)
importFrom(JuliaConnectoR,juliaImport)
importFrom(Matrix,Diagonal)
importFrom(Matrix,Matrix)
importFrom(Matrix,crossprod)
importFrom(Matrix,sparse.model.matrix)
Expand Down Expand Up @@ -64,6 +64,7 @@ importFrom(rlang,warn)
importFrom(stats,aggregate)
importFrom(stats,as.formula)
importFrom(stats,coef)
importFrom(stats,confint)
importFrom(stats,expand.model.frame)
importFrom(stats,formula)
importFrom(stats,model.frame)
Expand Down
36 changes: 36 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
# CRAN release: fwildclusterboot 0.15

- For rademacher weights, switches to `dqrng::dqrrademacher`. This leads to substabtial
performance increases (see below). But the random number generation changes slightly, so
you might no longer reproduce exactly the same weights draw under the same seeds, and in turn,
your bootstrap inferences might change slightly.
- For other changes, see the changelog for versions `0.13-0.14.3`, all of which have not
been published on CRAN.
- The package's lifecycle badge has been changed to `stable`, as there have not been any breaking API
changes in a while, and I do not plan any in the future.

```r
> library(bench)
>
> n <- 999999 * 100
>
> mark(
+ dqrrademacher(n),
+ dqrng::dqsample(
+ x = c(-1L, 1L),
+ size = n,
+ replace = TRUE
+ ),
+ iterations = 5,
+ check = FALSE
+ )
# A tibble: 2 × 13
expression min median itr/s…¹ mem_a…² gc/se…³ n_itr n_gc
<bch:expr> <bch:> <bch:> <dbl> <bch:b> <dbl> <int> <dbl>
1 dqrrademacher(n) 123ms 166ms 5.25 381MB 3.15 5 3
2 dqrng::dqsample(x = c(-1L, 1L), size = n, replace = TRUE) 615ms 647ms 1.47 763MB 1.47 5 5
# … with 5 more variables: total_time <bch:tm>, result <list>, memory <list>, time <list>, gc <list>, and
# abbreviated variable names ¹​`itr/sec`, ²​mem_alloc, ³​`gc/sec`
```


# fwildclusterboot 0.14.3

- Fix a bug with CI inversion when `r` was set to be close to the estimated parameter. (CI inversion failed). See [#138](https://github.com/s3alfisc/fwildclusterboot/issues/138). Thanks to Achim Zeileis & team for raising this issue!
Expand Down
4 changes: 2 additions & 2 deletions R/boot_algo_fastnwild.R
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ boot_algo_fastnwild <-
if (impose_null == TRUE) {
# should always be positive, point_estimate and t_stat need to have same
# sign, abs for security
pval_peak <- abs(point_estimate)
pval_peak <- point_estimate
} else if (impose_null == FALSE) {
pval_peak <- abs((point_estimate - r))
pval_peak <- (point_estimate - r)
}

invert_p_val(
Expand Down
16 changes: 13 additions & 3 deletions R/boottest_felm.R
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,12 @@ boottest.felm <- function(object,
}
}
}

check_engine_btype(
engine = engine,
bootstrap_type = bootstrap_type
)


if (!is.null(beta0)) {
rlang::abort(
Expand Down Expand Up @@ -454,14 +460,18 @@ boottest.felm <- function(object,

if (is.null(clustid)) {
heteroskedastic <- TRUE
if (engine == "R") {
if (engine %in% c("R", "WildBootTests.jl")) {
# heteroskedastic models should always be run through R-lean
engine <- "R-lean"
rlang::inform(
"The heteroskedastic bootstrap is only supported for `engine = 'R-lean'`,
Resetting the engine argument to 'R-lean'."
)
}
} else {
heteroskedastic <- FALSE
}

check_bootstrap_types(
param = param,
bootstrap_type = bootstrap_type
Expand Down Expand Up @@ -492,7 +502,7 @@ boottest.felm <- function(object,
fe = fe
)

preprocess <- preprocess2.felm(
preprocess <- preprocess_felm(
object = object,
clustid = clustid,
R = R_long,
Expand Down
17 changes: 13 additions & 4 deletions R/boottest_fixest.R
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,12 @@ boottest.fixest <- function(object,
}
}
}


check_engine_btype(
engine = engine,
bootstrap_type = bootstrap_type
)

if (!is.null(beta0)) {
rlang::abort(
c(
Expand Down Expand Up @@ -481,14 +486,18 @@ boottest.fixest <- function(object,

if (is.null(clustid)) {
heteroskedastic <- TRUE
if (engine == "R") {
if (engine %in% c("R", "WildBootTests.jl")) {
# heteroskedastic models should always be run through R-lean
engine <- "R-lean"
rlang::inform(
"The heteroskedastic bootstrap is only supported for `engine = 'R-lean'`,
Resetting the engine argument to 'R-lean'."
)
}
} else {
heteroskedastic <- FALSE
}

check_bootstrap_types(
param = param,
bootstrap_type = bootstrap_type
Expand Down Expand Up @@ -521,7 +530,7 @@ boottest.fixest <- function(object,
)

# preprocess the data: Y, X, weights, fixed_effect
preprocess <- preprocess2.fixest(
preprocess <- preprocess_fixest(
object = object,
clustid = clustid,
R = R_long,
Expand Down
2 changes: 1 addition & 1 deletion R/boottest_ivreg.R
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ boottest.ivreg <- function(object,


# preprocess data: X, Y, weights, fixed effects
preprocess <- preprocess2.ivreg(
preprocess <- preprocess_ivreg(
object = object,
clustid = clustid,
R = R,
Expand Down
12 changes: 8 additions & 4 deletions R/boottest_lm.R
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ boottest.lm <- function(object,
engine = engine,
bootstrap_type = bootstrap_type
)

if (!is.null(beta0)) {
rlang::abort(
c(
Expand Down Expand Up @@ -413,14 +413,18 @@ boottest.lm <- function(object,

if (is.null(clustid)) {
heteroskedastic <- TRUE
if (engine == "R") {
if (engine %in% c("R", "WildBootTests.jl")) {
# heteroskedastic models should always be run through R-lean
engine <- "R-lean"
rlang::inform(
"The heteroskedastic bootstrap is only supported for `engine = 'R-lean'`,
Resetting the engine argument to 'R-lean'."
)
}
} else {
heteroskedastic <- FALSE
}

check_bootstrap_types(
param = param,
bootstrap_type = bootstrap_type
Expand Down Expand Up @@ -453,7 +457,7 @@ boottest.lm <- function(object,
# now split into R, R-lean and WildBootTests.jl algos
# different pre-processing and different algo-functions

preprocess <- preprocess2.lm(
preprocess <- preprocess_lm(
object = object,
clustid = clustid,
R = R_long,
Expand Down
6 changes: 1 addition & 5 deletions R/get_weights.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@ get_weights <- function(type,
# (uses less memory
# than numeric)
rademacher = function(n) {
dqrng::dqsample(
x = c(-1L, 1L),
size = n,
replace = TRUE
)
dqrng::dqrrademacher(n)
},
mammen = function(n) {
sample(
Expand Down
2 changes: 1 addition & 1 deletion R/mboottest_felm.R
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ mboottest.felm <- function(object,

fedfadj <- 0L

preprocess <- preprocess2.felm(
preprocess <- preprocess_felm(
object = object,
clustid = clustid,
R = R,
Expand Down
2 changes: 1 addition & 1 deletion R/mboottest_fixest.R
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ mboottest.fixest <- function(object,
fe = fe
)

preprocess <- preprocess2.fixest(
preprocess <- preprocess_fixest(
object = object,
clustid = clustid,
R = R,
Expand Down
2 changes: 1 addition & 1 deletion R/mboottest_lm.R
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ mboottest.lm <- function(object,


# preprocess data: X, Y, weights, fixed effects
preprocess <- preprocess2.lm(
preprocess <- preprocess_lm(
object = object,
clustid = clustid,
R = R,
Expand Down
22 changes: 12 additions & 10 deletions R/methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#'
#' @details Technical Details
#' For technical details, either take a look at the references below, or check
#' out the [wild (cluster) bootstrap vignette](wild_bootstrap.html).
#' out the [wild (cluster) bootstrap vignette](https://s3alfisc.github.io/fwildclusterboot/articles/wild_bootstrap.html).
#'
#' @section Stata, Julia and Python Implementations:
#' The fast wild cluster bootstrap algorithms are further implemented in the
Expand Down Expand Up @@ -757,6 +757,7 @@ nobs.mboottest <- function(object, ...) {
#' @param ... Further arguments passed to or from other methods.
#' @param digits Number of rounding digits
#' @export
#' @importFrom stats confint
#' @method print boottest
#' @return A scalar containing the effective number of observations
#' used in `mboottest`
Expand All @@ -780,16 +781,17 @@ print.boottest <- function(x, ..., digits = 4) {
print(x$call)
cat("", "\n")

vals <- lapply(
c("p_val", "conf_int", "t_stat"),
function(y) {
round(x[[y]], digits = digits)
}
)
pval <- pval(x)
conf_int <- confint(x)
teststat <- teststat(x)

cat("p value:", vals[[1]], "\n")
cat("confidence interval:", vals[[2]], "\n")
cat("test statistic", vals[[3]], "\n")
pval <- round(pval, digits = digits)
teststat <- round(teststat, digits = digits)
conf_int <- ifelse(is.null(conf_int), NA, round(conf_int, digits))

cat("p value:", pval, "\n")
cat("confidence interval:", conf_int, "\n")
cat("test statistic", teststat, "\n")
}


Expand Down
9 changes: 9 additions & 0 deletions R/onLoad.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,17 @@

.onAttach <-
function(libname, pkgname) {

packageStartupMessage("\nNote that with version 0.15, rademacher weights are")
packageStartupMessage("drawn from `dqrng::dqrrademacher()` instead of `dqrng::dqsample()`.")
packageStartupMessage("This brings nice performance gains, but you might no longer be able to exactly reproduce")
packageStartupMessage("your bootstrap inferences under a given seed. If this is a ")
packageStartupMessage("requirement for you, please revert to `fwildclusterboot` version")
packageStartupMessage("0.13-0.14.3.")

packageStartupMessage("\nPlease cite as: \n")
packageStartupMessage(" Fischer & Roodman. (2021). fwildclusterboot: Fast Wild Cluster.")
packageStartupMessage(" Bootstrap Inference for Linear Regression Models.")
packageStartupMessage(" Available from https://cran.r-project.org/package=fwildclusterboot/.")

}
26 changes: 5 additions & 21 deletions R/preprocess2.R → R/preprocess_models.R
Original file line number Diff line number Diff line change
@@ -1,20 +1,4 @@
#' `preprocess2` is a S3 method that fetches data from several model
#' objectects for use with `boottest()`.
#'
#' @param object An objectect of type lm, fixest, felm or ivreg
#' @param ... other arguments
#' @noRd
#'
#' @importFrom Matrix Diagonal
#' @return An object of class `preprocess2`.
#' @srrstats {G2.8} *Software should provide appropriate conversion or dispatch
#' routines as part of initial pre-processing to ensure that all other
#' sub-functions of a package receive inputs of a single defined class or
#' type.* Similar preprocess method + run_bootstrap function.
preprocess2 <- function(object, ...) {
UseMethod("preprocess2")
}
preprocess2.fixest <-
preprocess_fixest <-
function(object,
clustid,
R,
Expand Down Expand Up @@ -213,7 +197,7 @@ preprocess2.fixest <-
}
res
}
preprocess2.felm <-
preprocess_felm <-
function(object,
clustid,
R,
Expand Down Expand Up @@ -388,7 +372,7 @@ preprocess2.felm <-
}
res
}
preprocess2.lm <-
preprocess_lm <-
function(object,
clustid,
R,
Expand Down Expand Up @@ -492,7 +476,7 @@ preprocess2.lm <-
class(res) <- c("preprocess", "ols")
res
}
preprocess2.ivreg <-
preprocess_ivreg <-
function(object,
clustid,
R,
Expand Down Expand Up @@ -1040,4 +1024,4 @@ get_cluster <-
cluster_bootcluster = cluster_bootcluster_df
)
res
}
}
Loading
Loading