Skip to content

Commit

Permalink
Vignette, doc, and Namespace updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ngreifer committed Mar 3, 2024
1 parent f68bb18 commit baf8a52
Show file tree
Hide file tree
Showing 30 changed files with 279 additions and 155 deletions.
9 changes: 5 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: WeightIt
Type: Package
Title: Weighting for Covariate Balance in Observational Studies
Version: 0.14.2.9002
Version: 0.14.2.9003
Authors@R: c(
person("Noah", "Greifer", role=c("aut", "cre"),
email = "noah.greifer@gmail.com",
Expand All @@ -11,7 +11,7 @@ Description: Generates balancing weights for causal effect estimation in observa
binary, multi-category, or continuous point or longitudinal treatments by easing and
extending the functionality of several R packages and providing in-house estimation methods.
Available methods include propensity score weighting using generalized linear models, gradient
boosting machines, the covariate balancing propensity score algorithm, Bayesian additive regression trees, and
boosting machines, the covariate balancing propensity score algorithm, inverse probability tilting, Bayesian additive regression trees, and
SuperLearner, and directly estimating balancing weights using entropy balancing, energy balancing, and optimization-based weights. Also
allows for assessment of weights and checking of covariate balance by interfacing directly
with the 'cobalt' package. See the vignette "Installing Supporting Packages" for instructions on how
Expand All @@ -24,7 +24,7 @@ Imports:
chk (>= 0.8.1), rlang (>= 1.1.0),
crayon,
backports (>= 1.4.1),
stats, utils
stats
Suggests:
CBPS (>= 0.18),
optweight (>= 0.2.4),
Expand All @@ -44,6 +44,7 @@ Suggests:
gbm (>= 2.1.3),
dbarts (>= 0.9-20),
misaem (>= 1.0.1),
utils,
knitr,
rmarkdown
License: GPL (>=2)
Expand All @@ -53,5 +54,5 @@ URL: https://ngreifer.github.io/WeightIt/,
BugReports: https://github.com/ngreifer/WeightIt/issues
VignetteBuilder: knitr
LazyData: true
RoxygenNote: 7.2.3
RoxygenNote: 7.3.1
Roxygen: list(markdown = TRUE)
5 changes: 0 additions & 5 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,5 @@ import(stats)
importFrom(crayon,italic)
importFrom(crayon,strikethrough)
importFrom(crayon,underline)
importFrom(graphics,boxplot)
importFrom(graphics,hist)
importFrom(graphics,par)
importFrom(graphics,plot)
importFrom(utils,combn)
importFrom(utils,data)
importFrom(utils,hasName)
6 changes: 5 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ WeightIt News and Updates

# WeightIt (development version)

* Added inverse probability tilting (IPT) as described by Graham, Pinto, and Egel (2012), which can be requested by setting `method = "ipt"`. Thus is similar to entropy balancing and CBPS in that it enforces exact balance and yields a propensity score, but has some theoretical advantages to both methods. A version is available for continuous treatments, but it should be used with caution (it is essentially the same as CBPS in this case). IPT does not rely on any other packages and runs very quickly.

* New function `calibrate()` to apply Platt scaling to calibrate propensity scores as recommended by [Gutman et al. (2022)](http://arxiv.org/abs/2211.01221).

* A new argument `quantile` can be supplied to `weightit()` with all the methods that accept `moments` and `int` (`"ebal"`, `"npcbps"`, `"optweight"`, and `"energy"`). This allows one to request balance on the quantiles of the covariates, which can add some robustness as demonstrated by [Beręsewicz (2023)](https://arxiv.org/abs/2310.11969).
Expand All @@ -19,7 +21,9 @@ WeightIt News and Updates

* Warning messages now display immediately rather than at the end of evaluation.

* The vignettes have been changed to use a slightly different estimator for weighted g-computation. The estimated weights are no longer to be included in the call to `avg_comparisons()`, etc.; that is, they are only used to fit the outcome model. This makes the estimators more consistent with other software, including `teffects ipwra` in Stata, and most of the literature on weighted g-computation. Note this will not effect any estimates for the ATT or ATC and will only yield at most minor changes for the ATE. For other estimands, the weights are still included.
* The vignettes have been changed to use a slightly different estimator for weighted g-computation. The estimated weights are no longer to be included in the call to `avg_comparisons()`, etc.; that is, they are only used to fit the outcome model. This makes the estimators more consistent with other software, including `teffects ipwra` in Stata, and most of the literature on weighted g-computation. Note this will not effect any estimates for the ATT or ATC and will only yield at most minor changes for the ATE. For other estimands (e.g., ATO), the weights are still to be included.

* The word "multinomial" to describe treatments with more than two categories has been replaced with "multi-category" in all documentation and messages.

* Transferred all help files to Roxygen and reorganized package scripts.

Expand Down
8 changes: 2 additions & 6 deletions R/SHARED.R
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,6 @@ strsplits <- function(x, splits, fixed = TRUE, ...) {
for (split in splits) x <- unlist(strsplit(x, split, fixed = TRUE, ...))
return(x[x != ""]) # Remove empty values
}
c.factor <- function(..., recursive = TRUE) {
#c() for factors
unlist(list(...), recursive = recursive)
}
can_str2num <- function(x) {
if (is.numeric(x) || is.logical(x)) return(TRUE)
nas <- is.na(x)
Expand All @@ -208,7 +204,7 @@ can_str2num <- function(x) {
}
str2num <- function(x) {
nas <- is.na(x)
if (!is_(x, c("numeric", "logical"))) x <- as.character(x)
if (!is.numeric(x) && !is.logical(x)) x <- as.character(x)
suppressWarnings(x_num <- as.numeric(x))
is.na(x_num[nas]) <- TRUE
x_num
Expand Down Expand Up @@ -473,7 +469,7 @@ bw.nrd <- function(x) {
#R's bw.nrd doesn't always work, but bw.nrd0 does
bw.nrd0(x)*1.06/.9
}
quantile.w <- function(x, probs = seq(0, 1, 0.25), w = NULL, na.rm = FALSE, ...) {
w.quantile <- function(x, probs = seq(0, 1, 0.25), w = NULL, na.rm = FALSE, ...) {

n <- length(x)
if (n == 0 || (!isTRUE(na.rm) && anyNA(x))) {
Expand Down
6 changes: 3 additions & 3 deletions R/functions_for_processing.R
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ int.poly.f <- function(d, ex = NULL, int = FALSE, poly = 1, center = TRUE, ortho

out
}
quantile.f <- function(d, qu = NULL, s.weights = NULL, focal = NULL, treat = NULL, const = 2000) {
quantile_f <- function(d, qu = NULL, s.weights = NULL, focal = NULL, treat = NULL, const = 2000) {
# Creates new variables for use in balance quantiles. `qu` is a list of quantiles for each
# continuous variable in `d`, and returns a matrix with a column for each requested quantile
# of each variable, taking on 0 for values less than the quantile, .5 for values at the quantile,
Expand Down Expand Up @@ -577,7 +577,7 @@ quantile.f <- function(d, qu = NULL, s.weights = NULL, focal = NULL, treat = NUL
do.call("cbind", lapply(names(qu), function(i) {
target <- if (is_null(focal)) d[,i] else d[treat == focal, i]
out <- do.call("cbind", lapply(qu[[i]], function(q) {
plogis(const * (d[,i] - quantile.w(target, q, s.weights)))
plogis(const * (d[,i] - w.quantile(target, q, s.weights)))
}))

colnames(out) <- paste0(i, "_", qu[[i]])
Expand Down Expand Up @@ -993,7 +993,7 @@ get_dens_fun <- function(use.kernel = FALSE, bw = NULL, adjust = NULL, kernel =
densfun
}

get.w.from.ps <- function(ps, treat, estimand = "ATE", focal = NULL, subclass = NULL, stabilize = FALSE) {
.get_w_from_ps_internal <- function(ps, treat, estimand = "ATE", focal = NULL, subclass = NULL, stabilize = FALSE) {
#Batch turn PS into weights; primarily for output of predict.gbm
# Assumes a (0,1) treatment if binary, with ATT already processed
if (is_null(dim(ps))) {
Expand Down
2 changes: 1 addition & 1 deletion R/weightit2ebal.R
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ weightit2ebal <- function(covs, treat, s.weights, subset, estimand, focal,

covs <- cbind(covs, int.poly.f(covs, poly = moments, int = int, center = TRUE))

covs <- cbind(covs, quantile.f(covs, qu = A[["quantile"]], s.weights = s.weights,
covs <- cbind(covs, quantile_f(covs, qu = A[["quantile"]], s.weights = s.weights,
focal = focal, treat = treat))

for (i in seq_col(covs)) covs[,i] <- make.closer.to.1(covs[,i])
Expand Down
4 changes: 2 additions & 2 deletions R/weightit2energy.R
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ weightit2energy <- function(covs, treat, s.weights, subset, estimand, focal, mis
}

if (is_not_null(A[["quantile"]])) {
qu <- quantile.f(covs, qu = A[["quantile"]], s.weights = s.weights)
qu <- quantile_f(covs, qu = A[["quantile"]], s.weights = s.weights)

targets <- col.w.m(qu, s.weights)

Expand Down Expand Up @@ -256,7 +256,7 @@ weightit2energy <- function(covs, treat, s.weights, subset, estimand, focal, mis
}

if (is_not_null(A[["quantile"]])) {
qu <- quantile.f(covs, qu = A[["quantile"]], s.weights = s.weights,
qu <- quantile_f(covs, qu = A[["quantile"]], s.weights = s.weights,
focal = focal, treat = treat)

targets <- col.w.m(qu[in_focal,, drop = FALSE], s.weights[in_focal])
Expand Down
6 changes: 3 additions & 3 deletions R/weightit2gbm.R
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ weightit2gbm <- function(covs, treat, s.weights, estimand, focal, subset,
}

ps <- gbm::predict.gbm(fit, n.trees = iters.grid, type = "response", newdata = covs)
w <- get.w.from.ps(ps, treat = treat, estimand = estimand, focal = focal, stabilize = stabilize, subclass = subclass)
w <- .get_w_from_ps_internal(ps, treat = treat, estimand = estimand, focal = focal, stabilize = stabilize, subclass = subclass)
if (trim.at != 0) w <- suppressMessages(apply(w, 2, trim, at = trim.at, treat = treat))

iter.grid.balance <- apply(w, 2, cobalt::bal.compute, x = init)
Expand All @@ -365,7 +365,7 @@ weightit2gbm <- function(covs, treat, s.weights, estimand, focal, subset,
}

ps <- gbm::predict.gbm(fit, n.trees = iters.to.check, type = "response", newdata = covs)
w <- get.w.from.ps(ps, treat = treat, estimand = estimand, focal = focal, stabilize = stabilize, subclass = subclass)
w <- .get_w_from_ps_internal(ps, treat = treat, estimand = estimand, focal = focal, stabilize = stabilize, subclass = subclass)
if (trim.at != 0) w <- suppressMessages(apply(w, 2, trim, at = trim.at, treat = treat))

iter.grid.balance.fine <- apply(w, 2, cobalt::bal.compute, x = init)
Expand Down Expand Up @@ -426,7 +426,7 @@ weightit2gbm <- function(covs, treat, s.weights, estimand, focal, subset,
if (best.loss < current.best.loss) {
best.fit <- fit
best.ps <- gbm::predict.gbm(fit, n.trees = best.tree, type = "response", newdata = covs)
best.w <- drop(get.w.from.ps(best.ps, treat = treat, estimand = estimand, focal = focal, stabilize = stabilize, subclass = subclass))
best.w <- drop(.get_w_from_ps_internal(best.ps, treat = treat, estimand = estimand, focal = focal, stabilize = stabilize, subclass = subclass))
# if (trim.at != 0) best.w <- suppressMessages(trim(best.w, at = trim.at, treat = treat))
current.best.loss <- best.loss
best.tune.index <- i
Expand Down
4 changes: 2 additions & 2 deletions R/weightit2ipt.R
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ weightit2ipt <- function(covs, treat, s.weights, subset, estimand, focal,

covs <- cbind(covs, int.poly.f(covs, poly = moments, int = int, center = TRUE))

covs <- cbind(covs, quantile.f(covs, qu = A[["quantile"]], s.weights = s.weights,
covs <- cbind(covs, quantile_f(covs, qu = A[["quantile"]], s.weights = s.weights,
focal = focal, treat = treat))

for (i in seq_col(covs)) covs[,i] <- make.closer.to.1(covs[,i])
Expand Down Expand Up @@ -239,7 +239,7 @@ weightit2ipt.multi <- function(covs, treat, s.weights, subset, estimand, focal,

covs <- cbind(covs, int.poly.f(covs, poly = moments, int = int, center = TRUE))

covs <- cbind(covs, quantile.f(covs, qu = A[["quantile"]], s.weights = s.weights,
covs <- cbind(covs, quantile_f(covs, qu = A[["quantile"]], s.weights = s.weights,
focal = focal, treat = treat))

for (i in seq_col(covs)) covs[,i] <- make.closer.to.1(covs[,i])
Expand Down
2 changes: 1 addition & 1 deletion R/weightit2npcbps.R
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ weightit2npcbps <- function(covs, treat, s.weights, subset, missing, moments, in

covs <- cbind(covs, int.poly.f(covs, poly = moments, int = int))

covs <- cbind(covs, quantile.f(covs, qu = A[["quantile"]], s.weights = s.weights))
covs <- cbind(covs, quantile_f(covs, qu = A[["quantile"]], s.weights = s.weights))

for (i in seq_col(covs)) covs[,i] <- make.closer.to.1(covs[,i])

Expand Down
2 changes: 1 addition & 1 deletion R/weightit2optweight.R
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ weightit2optweight <- function(covs, treat, s.weights, subset, estimand, focal,

covs <- cbind(covs, int.poly.f(covs, poly = moments, int = int))

covs <- cbind(covs, quantile.f(covs, qu = A[["quantile"]], s.weights = s.weights,
covs <- cbind(covs, quantile_f(covs, qu = A[["quantile"]], s.weights = s.weights,
focal = focal, treat = treat))

for (i in seq_col(covs)) covs[,i] <- make.closer.to.1(covs[,i])
Expand Down
2 changes: 1 addition & 1 deletion R/weightit2super.R
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ weightit2super.cont <- function(covs, treat, s.weights, subset, stabilize, missi
Z[Z[,i] < tol, i] <- tol
Z[Z[,i] > 1-tol, i] <- 1-tol
}
w_mat <- get.w.from.ps(Z, treat = Y, estimand = estimand)
w_mat <- .get_w_from_ps_internal(Z, treat = Y, estimand = estimand)
cvRisk <- apply(w_mat, 2, cobalt::bal.compute, x = init)

names(cvRisk) <- libraryNames
Expand Down
41 changes: 22 additions & 19 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ knitr::opts_chunk$set(
------
### Overview

`WeightIt` is a one-stop package to generate balancing weights for point and longitudinal treatments in observational studies. Contained within `WeightIt` are methods that call on other R packages to estimate weights. The value of `WeightIt` is in its unified and familiar syntax used to generate the weights, as each of these other packages have their own, often challenging to navigate, syntax. `WeightIt` extends the capabilities of these packages to generate weights used to estimate the ATE, ATT, ATC, and other estimands for binary or multinomial treatments, and treatment effects for continuous treatments when available. In these ways, `WeightIt` does for weighting what `MatchIt` has done for matching, and `MatchIt` users will find the syntax familiar.
`WeightIt` is a one-stop package to generate balancing weights for point and longitudinal treatments in observational studies. Contained within `WeightIt` are methods that call on other R packages to estimate weights. The value of `WeightIt` is in its unified and familiar syntax used to generate the weights, as each of these other packages have their own, often challenging to navigate, syntax. `WeightIt` extends the capabilities of these packages to generate weights used to estimate the ATE, ATT, ATC, and other estimands for binary or multi-category treatments, and treatment effects for continuous treatments when available. In these ways, `WeightIt` does for weighting what `MatchIt` has done for matching, and `MatchIt` users will find the syntax familiar.

For a complete vignette, see the [website](https://ngreifer.github.io/WeightIt/articles/WeightIt.html) for `WeightIt` or `vignette("WeightIt")`.

Expand Down Expand Up @@ -78,31 +78,34 @@ The table below contains the available methods in `WeightIt` for estimating weig
-------------- | -------------------- | --------
**Binary** | Binary regression PS (`"glm"`) | various
- | Generalized boosted modeling PS (`"gbm"`) | `gbm`
- | Covariate Balancing PS (`"cbps"`) | `CBPS`
- | Non-Parametric Covariate Balancing PS (`"npcbps"`) | `CBPS`
- | Covariate balancing PS (`"cbps"`) | `CBPS`
- | Non-parametric covariate balancing PS (`"npcbps"`) | `CBPS`
- | Entropy Balancing (`"ebal"`) | -
- | Optimization-Based Weights (`"optweight"`) | `optweight`
- | Inverse probability tilting (`"ipt"`) | -
- | Optimization-based Weights (`"optweight"`) | `optweight`
- | SuperLearner PS (`"super"`) | `SuperLearner`
- | Bayesian Additive Regression Trees PS (`"bart"`) | `dbarts`
- | Energy Balancing (`"energy"`) | -
**Multinomial** | Multinomial regression PS (`"glm"`) | various
- | Bayesian additive regression trees PS (`"bart"`) | `dbarts`
- | Energy balancing (`"energy"`) | -
**Multi-categoryl** | Multinomial regression PS (`"glm"`) | various
- | Generalized boosted modeling PS (`"gbm"`) | `gbm`
- | Covariate Balancing PS (`"cbps"`) | `CBPS`
- | Non-Parametric Covariate Balancing PS (`"npcbps"`) | `CBPS`
- | Entropy Balancing (`"ebal"`) | -
- | Optimization-Based Weights (`"optweight"`) | `optweight`
- | Covariate balancing PS (`"cbps"`) | `CBPS`
- | Non-Parametric covariate balancing PS (`"npcbps"`) | `CBPS`
- | Entropy balancing (`"ebal"`) | -
- | Inverse probability tilting (`"ipt"`) | -
- | Optimization-based weights (`"optweight"`) | `optweight`
- | SuperLearner PS (`"super"`) | `SuperLearner`
- | Bayesian Additive Regression Trees PS (`"bart"`) | `dbarts`
- | Energy Balancing (`"energy"`) | -
- | Bayesian additive regression trees PS (`"bart"`) | `dbarts`
- | Energy balancing (`"energy"`) | -
**Continuous** | Generalized linear model GPS (`"glm"`) | -
- | Generalized boosted modeling GPS (`"gbm"`) | `gbm`
- | Covariate Balancing GPS (`"cbps"`) | `CBPS`
- | Non-Parametric Covariate Balancing GPS (`"npcbps"`) | `CBPS`
- | Entropy Balancing (`"ebal"`) | -
- | Optimization-Based Weights (`"optweight"`) | `optweight`
- | Covariate balancing GPS (`"cbps"`) | `CBPS`
- | Non-Parametric covariate balancing GPS (`"npcbps"`) | `CBPS`
- | Entropy balancing (`"ebal"`) | -
- | Inverse probability tilting (`"ipt"`) | -
- | Optimization-based weights (`"optweight"`) | `optweight`
- | SuperLearner GPS (`"super"`) | `SuperLearner`
- | Bayesian Additive Regression Trees GPS (`"bart"`) | `dbarts`
- | Distance Covariance Optimal Weighting (`"energy"`) | -
- | Bayesian additive regression trees GPS (`"bart"`) | `dbarts`
- | Distance covariance optimal weighting (`"energy"`) | -

In addition, `WeightIt` implements the subgroup balancing propensity score using the function `sbps()`. Several other tools and utilities are available.

Expand Down
Loading

0 comments on commit baf8a52

Please sign in to comment.