使用「;获得;在dplyr中

使用「;获得;在dplyr中,r,dplyr,plyr,R,Dplyr,Plyr,其背景是,我有一些在一些地方使用plyr的遗留代码,直到几天前,plyr还没有更新以使其与R3.5兼容。我认为这是对plyr支持减少的一个信号,因此我正在考虑将plyr命令更改为dplyr。遗留代码中的ddply命令涉及一些“get”命令,用于引用名称包含在变量中的列。直接翻译将涉及以下类型的代码(一个人为的例子,但它说明了这一点)。它似乎可以工作,并使其与原始代码保持最接近,但这样做有什么陷阱吗?我得到的印象是,这不是制造商批准的使用dplyr编程的方式 示例代码: library("dply

其背景是,我有一些在一些地方使用plyr的遗留代码,直到几天前,plyr还没有更新以使其与R3.5兼容。我认为这是对plyr支持减少的一个信号,因此我正在考虑将plyr命令更改为dplyr。遗留代码中的ddply命令涉及一些“get”命令,用于引用名称包含在变量中的列。直接翻译将涉及以下类型的代码(一个人为的例子,但它说明了这一点)。它似乎可以工作,并使其与原始代码保持最接近,但这样做有什么陷阱吗?我得到的印象是,这不是制造商批准的使用dplyr编程的方式
示例代码:

library("dplyr")
testFunction <- function(dataset, groupcol, varcol){
  summaryTable <- dataset %>% 
    group_by(get(groupcol)) %>%
    summarise(mean_var = mean(get(varcol)),
              sd_var = sd(get(varcol)))
  return(summaryTable)
}
testGroup <- "cyl"
testVar <- "mpg"
testFunction(mtcars, testGroup, testVar)
库(“dplyr”)
测试函数%
总结(平均值=平均值(获取(varcol)),
sd_var=sd(get(varcol)))
返回(汇总表)
}

testGroup我们可以使用
sym
将其转换为
符号
如果我们传递一个字符串变量,然后使用
进行计算

testFunction <- function(dataset, groupcol, varcol){

varcol <- rlang::sym(varcol)
 dataset %>% 
    group_by(!! rlang::sym(groupcol)) %>%
    summarise(mean_var = mean(!! varcol),
          sd_var = sd(!! varcol))

 }
testFunction(mtcars, testGroup, testVar)
# A tibble: 3 x 3
#    cyl mean_var sd_var
#  <dbl>    <dbl>  <dbl>
#1     4     26.7   4.51
#2     6     19.7   1.45
#3     8     15.1   2.56

最新版本的
dplyr
允许使用bang-bang运算符(
!!
)将变量插入函数调用中。应该避免使用
get()
函数。您可以通过以下方式修复函数

testFunction <- function(dataset, groupcol, varcol){
  groupcol <- as.name(groupcol)
  varcol <- as.name(varcol)
  summaryTable <- dataset %>% 
    group_by(!!groupcol) %>%
    summarise(mean_var = mean(!!varcol),
              sd_var = sd(!!varcol))
  return(summaryTable)
}
testGroup <- "cyl"
testVar <- "mpg"
testFunction(mtcars, testGroup, testVar)

testFunction就我个人而言,我反对这里的一些正统说法,我只使用
get
来处理以下一些情况:

testFunction <- function(dataset, groupcol, varcol){
  dataset %>% 
    group_by(get(groupcol)) %>%
    summarise(mean_var = mean(get(varcol)),
              sd_var = sd(get(varcol)))
}

我发现
get(x)
更简单、更直观!!as.name(x)
!!rlang::sym(x)
,考虑到过去几年中所有引用/取消引用实用程序的波动性,未来几年我可能会求助于
命名空间中的内置函数。

谢谢。出于兴趣,关于我最初的问题,为什么要避免使用get函数?只是教条,还是有功能上的原因?我想bang-bang比get短3个字符@Knackiedoo我想这可能更像是一个风格指南建议。要显示一个得到错误结果的示例并不容易,但是当使用
get()
时,并不总是清楚要从何处提取特定变量。通常,当我在R代码中看到
get()/assign()
时,是因为其他人从其他语言复制算法,而不是真正以“R方式”做事。使用符号和表达式(或表达式)或dplyr鼓励的quosures允许更灵活的代码,并且在使用比单个列名更复杂的表达式时表现更好。谢谢。MrFlick给出的答案与此类似,但在使用bang-bang之前没有转换成符号,而且它似乎可以工作。是否有特定的原因或情况需要首先转换为符号?按_at分组是一个很好的建议,但在所讨论的实际案例中,总结不会削减它,因为总结实际上比对所有变量应用单个函数复杂得多。@Knackiedoo
as.name
正在转换为symbol
str(as.name(testGroup))#symbol cyl
如果传递的参数是字符串,则它需要更改为symbol的条件。如果是不带引号的字符串,可以使用
enquo
将其转换为quosure,然后执行
好的,我明白了。我非常确定as.name的理论编码问题不太可能是个问题,因此我将坚持使用基函数而不是sym。只是出于兴趣,我很好奇为什么“get”会遭到这样的反对。我刚才提到的sym help“与as.name()相反,它们事先将字符串转换为本机编码”。我相信你的话,get可能会出现环境/位置问题。只是想学习!
testFunction <- function(dataset, groupcol, varcol){
  groupcol <- as.name(groupcol)
  varcol <- as.name(varcol)
  summaryTable <- dataset %>% 
    group_by(!!groupcol) %>%
    summarise(mean_var = mean(!!varcol),
              sd_var = sd(!!varcol))
  return(summaryTable)
}
testGroup <- "cyl"
testVar <- "mpg"
testFunction(mtcars, testGroup, testVar)
testFunction <- function(dataset, groupcol, varcol){
  dataset %>% 
    group_by(get(groupcol)) %>%
    summarise(mean_var = mean(get(varcol)),
              sd_var = sd(get(varcol)))
}
testFunction <- function(dataset, groupcol, varcol){
  dataset %>% 
    group_by(.data[[groupcol]]) %>%
    summarise(mean_var = mean(.data[[varcol]]),
              sd_var = sd(.data[[varcol]]))
}