Search code examples
rtidyevalnsenon-standard-evaluation

inject() function from rlang package cannot work with Predict() function from rms package in R


Context

I am learning use tidy eval to write my own function.

If I calculate hr1 without using tidy eval, the code works fine, such as:

hr1 = Predict(fit, meal.cal = q, fun = exp, ref.zero = TRUE)

When I use rlang::inject() and rms::Predict() jointly to calculate hr1, an error occurs, such as:

hr1= rlang::inject(Predict(fit, !!x = q, fun = exp, ref.zero = TRUE))

Question

How to use rlang::object() and rms::Predict() correctly jointly?

Reproducible code

library(survival)
library(rms)
data(cancer)

x = sym('meal.cal')

q = quantile(lung[[x]], probs = c(0.05, 0.35, 0.65, 0.95), na.rm = T)

fit = rlang::inject(cph(Surv(time, status) ~ rcs(!!x), data = lung))

dd = datadist(lung)
options(datadist = 'dd') # Predict() cannot work without set the options

hr1 = Predict(fit, meal.cal = q, fun = exp, ref.zero = TRUE) # Run successful
head(hr1)
# meal.cal      yhat     lower    upper
# 1      338 1.2486497 0.7310498 2.132722
# 2      825 0.9916446 0.7766063 1.266226
# 3     1039 1.0245228 0.8826652 1.189179
# 4     1425 1.0558754 0.6322319 1.763392
# 
# Response variable (y):  
#   
#   Limits are 0.95 confidence limits

hr1= rlang::inject(Predict(fit, !!x = q, fun = exp, ref.zero = TRUE)) # Run failed
# Error: unexpected '=' in "hr1= rlang::inject(Predict(fit, !!x ="


Solution

  • The left-hand side of a named parameter (i.e. = inside a call) must be a name, it cannot be an expression. To work around this limitation, you can use splicing here:

    hr1 = rlang::inject(Predict(fit, !!! setNames(list(q), "foo"), fun = exp, ref.zero = TRUE))
    

    In general, ‘rlang’ allows := in the place of = for named arguments to work around the R syntax limitation but for some reason inject does not support this.