通过使用权重来rlang GLM()

问题描述 投票:2回答:1

我想通过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()。思考大为赞赏。

r glm rlang tidyeval
1个回答
2
投票

问题是,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), ...) )
}
© www.soinside.com 2019 - 2024. All rights reserved.