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")
}