我想通过weights
通过功能glm()
,而不必使用eval(substitute())
或do.call()
方法,但使用rlang
。
这描述了一个更复杂的底层函数。
# Toy data
mydata = dplyr::tibble(outcome = c(0,0,0,0,0,0,0,0,1,1,1,1,1,1),
group = c(0,1,0,1,0,1,0,1,0,1,0,1,0,1),
wgts = c(1,1,1,1,1,1,1,1,1,1,1,1,1,1)
)
# This works
glm(outcome ~ group, data = mydata)
# This works
glm(outcome ~ group, data = mydata, weights = wgts)
library(rlang)
# Function not passing weights
myglm <- function(.data, y, x){
glm(expr(!! enexpr(y) ~ !! enexpr(x)), data = .data)
}
# This works
myglm(mydata, outcome, group)
# Function passing weights
myglm2 <- function(.data, y, x, weights){
glm(expr(!! enexpr(y) ~ !! enexpr(x)), `weights = !! enexpr(weights)`, data = .data)
}
# This doesn't work
myglm2(mydata, outcome, group, wgts)
(蜱是突出显示)。
我知道这里的权重说法是不对的,我已经尝试做这一切失败的许多不同的方式。实际的功能将被传递到一个版本purrr:map()
或purrr:invoke()
的,这就是为什么我想避免一个简单的do.call()
。思考大为赞赏。
问题是,glm()
可以识别的表达被提供给其weights
的说法,但不支持quasiquotation,因为它使用的不是quote()
基础substitute()
/ eval()
/ rlang
机制。 This causes problems for nested expression arithmetic。
要解决它的方法之一是组成整个glm
表达,然后评估它。您可以使用...
提供可选参数。
myglm2 <- function( .data, y, x, weights, ... ) {
myglm <- expr( glm(!!enexpr(y) ~ !!enexpr(x), data=.data,
weights = !!enexpr(weights), ...) )
eval(myglm)
}
myglm2(mydata, outcome, group)
# Call: glm(formula = outcome ~ group, data = .data)
myglm2(mydata, outcome, group, wgts)
# Call: glm(formula = outcome ~ group, data = .data, weights = wgts)
myglm2(mydata, outcome, group, wgts, subset=7:10)
# Call: glm(formula = outcome ~ group, data = .data, weights = wgts,
# subset = ..1)
# While masked as ..1, the 7:10 is nevertheless correctly passed to glm()
要关注@梅西的建议,你可以封装表达组成/评估到一个独立的功能:
value <- function( e ) {eval(enexpr(e), caller_env())}
myglm2 <- function( .data, y, x, weights, ... ) {
value( glm(!!enexpr(y) ~ !!enexpr(x), data=.data,
weights = !!enexpr(weights), ...) )
}