I want to pass a vector of column names to purrr::map() and iteratively pass them to the grf::causal_forest() function. In attempting this, i get an error that the values i'm passing to causal_forest() are not vectors (which is required) even though they definitely are.
For example, say I have this df
n <- 500
p <- 5
X <- matrix(rnorm(n * p), n, p)
W <- rbinom(n, 1, 0.5)
Y1 <- pmax(X[, 1], 0) * W X[, 2] pmin(X[, 3], 0) rnorm(n)
Y2 <- pmax(X[, 1], 0) * W X[, 2] pmin(X[, 3], 0) rnorm(n)
Y3 <- pmax(X[, 1], 0) * W X[, 2] pmin(X[, 3], 0) rnorm(n)
df <- data.frame(Y1, Y2, Y3, W, X)
head(df)
Y1 Y2 Y3 W X1 X2 X3 X4 X5
1 0.5457143 1.933581483 2.38474639 1 -0.788463384 0.9146194 0.73684926 -0.51268651 -0.53317046
2 0.9640213 -1.098133573 1.15639726 1 0.008873619 1.1513535 -1.09108874 0.10308198 1.46560149
3 0.8839862 0.005357524 1.26430215 1 1.588380125 -0.9261196 0.35219255 0.81017210 -1.86847771
4 0.1424579 -0.783984941 -0.01038922 0 2.391068797 0.3080699 -0.94651780 1.92707015 0.42646239
5 0.1771250 0.484711614 -1.95481918 1 0.058835623 0.2541232 -0.05696465 0.01781394 -0.07254417
6 -1.8144585 -1.972902090 -1.47101855 1 -0.518724916 -1.1474859 0.94850272 0.80635703 0.72156403
Where Y* are the dependent variables, X* is the covariate matrix, and W is a binary treatment indicator. I can estimate the model with just a single value of Y* like so
library(grf)
c_forest <- causal_forest(
X = X,
Y = df$Y1,
W = df$W)
ate_c_forest <- average_treatment_effect(
c_forest,
target.sample = "overlap")
ate_c_forest
estimate std.err
0.12262543 0.09578717
But I want to iterate over each value of Y1, Y2, and Y3 using map(), then extract the estimate and std.err for the output of each call to average_treatment_effect(), and put these inside a tibble. So I wrote this small function
Y_n <- c("Y1", "Y2", "Y3")
names(Y_n) <- Y_n
grf_fcn <- function(.x){
Y <- df$.x
W <- df$W
c_forest <- causal_forest(
X = X,
W = W,
Y = Y)
ate_c_forest <- average_treatment_effect(
c_forest,
target.sample = "overlap")
}
## call function
library(purrr)
grf_results <- purrr::map(
.x = tidyselect::all_of(Y_n),
.f = grf_fcn)
However, when I attempt to call the function it returns the error "Error in validate_observations(Y, X) : Observations (W, Y, Z or D) must be vectors." I find this curious as Y* and W are vectors. E.g.
> is.vector(df$Y1)
[1] TRUE
> is.vector(df$W)
[1] TRUE
Can anyone see where i'm going wrong here? Or is this a bug of some kind?
CodePudding user response:
To better understand where's the problem in your function, compare the output of the two following calls to map.
This one is the one you are using, it will return NULL:
purrr::map(tidyselect::all_of(Y_n), function(x) { df$x })
This one uses bracket notation, it will return the expected values:
purrr::map(tidyselect::all_of(Y_n), function(x) { df[[x]] })
This is a quirk of map and honestly I'm not quite sure what's going on under the hood, but at least we know how to modify your function to get your desired results:
grf_fcn <- function(x){
Y <- df[[x]]
W <- df$W
c_forest <- causal_forest(
X = X,
W = W,
Y = Y)
ate_c_forest <- average_treatment_effect(
c_forest,
target.sample = "overlap")
}
