编程功能:DPLYR和PURRR中的NSE

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

目前我在尝试使用dplyr和purrr完成的一些计算包装函数时遇到了非标准评估的一些问题。

我已经阅读过关于NSE的内容,并且我认为我知道我的功能无法正常工作的地方 - 但是,我无法弄清楚为什么会这样。

例如,我想围绕以下计算包装一个函数,其中分组变量以及新变量的名称,使用的分类变量和均值的输入变量应该是动态的:

 Data <- Data %>%
  group_by(WeekBeforeRelease) %>%
  mutate(visitors_genreother_instr = map_dbl(Genre_Category, ~ mean(Visitors[Genre_Category != .x]))) %>%
  ungroup() %>%
  as.data.frame()

使用NSE描述here,将此功能转换为以下内容:

Function_Other <- function(ENDOGVAR, VARNAME, GROUP_MOVIE, GROUP_TIME){

  ENDOGVAR <- enquo(ENDOGVAR)
  VARNAME <- quo_name(enquo(VARNAME))
  GROUP_MOVIE <- enquo(GROUP_MOVIE)
  GROUP_TIME <- enquo(GROUP_TIME)

  Data <<- Data %>%
    group_by(!!GROUP_TIME) %>%
    mutate(!!VARNAME := map_dbl(!!GROUP_MOVIE, ~mean(!!ENDOGVAR[!!GROUP_MOVIE != .x]))) %>%
    ungroup() %>%
    as.data.frame()
}

但是,这似乎不能很好地处理平均计算中带括号的子集。如果我用Visitors替换!! ENDOGVAR,一切正常并按预期工作。但是,它会产生以下错误:

Error in NextMethod("[") : object '.x' not found 

我很高兴能帮助我理解这个问题。

非常感谢提前!

隆多

r tidyverse purrr nse
1个回答
0
投票

我们可以将!!包装在大括号中以避免任何操作优先级,现在应该可以正常工作

library(tidyverse)
Function_Other <- function(ENDOGVAR, VARNAME, GROUP_MOVIE, GROUP_TIME){

  ENDOGVAR <- enquo(ENDOGVAR)
  VARNAME <- quo_name(enquo(VARNAME))
  GROUP_MOVIE <- enquo(GROUP_MOVIE)
  GROUP_TIME <- enquo(GROUP_TIME)

  Data %>%
    group_by(!!GROUP_TIME) %>%
    mutate(!!VARNAME := map_dbl(!!GROUP_MOVIE, ~
           mean((!!ENDOGVAR)[(!!GROUP_MOVIE) != .x]))) %>%
    ungroup() %>%
    as.data.frame()

}


Data <- mtcars
out <- Function_Other(mpg, newcol, am, gear)
head(out, 3)
#   mpg cyl disp  hp drat    wt  qsec vs am gear carb newcol
#1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  21.05
#2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4  21.05
#3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  21.05

Update

使用rlang 0.4.0(使用dplyr 0.8.2测试),我们也可以使用{{...}}替换,引用和取消引用。上一个函数可以写成

Function_OtherN <- function(ENDOGVAR, VARNAME, GROUP_MOVIE, GROUP_TIME){  


  Data %>%
    group_by({{GROUP_TIME}}) %>%
    mutate({{VARNAME}} := map_dbl({{GROUP_MOVIE}}, ~
           mean({{ENDOGVAR}}[{{GROUP_MOVIE}} != .x]))) %>%
    ungroup() %>%
    as.data.frame()

}


out1 <- Function_OtherN(mpg, newcol, am, gear)

- 检查以前的输出

identical(out1, out)
[1] TRUE
© www.soinside.com 2019 - 2024. All rights reserved.