dplyr:带有引用变量名称的mutate的标准评估

时间:2015-05-07 17:37:56

标签: r dplyr

我将如何使用mutate(我的推测是我在寻找标准评估,因此mutate_,但我并不完全自信在这一点上)当使用接受变量名称列表的函数时,例如:

createSum = function(data, variableNames) {
  data %>% 
    mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
                            var = as.name(paste(as.character(variableNames), collapse =","))))

}

这是一个MWE,它将功能剥离到其核心逻辑并演示我想要实现的目标:

library(dplyr)
library(lazyeval)

# function to make random table with given column names
makeTable = function(colNames, sampleSize) {
  liSample = lapply(colNames, function(week) {
    sample = rnorm(sampleSize)
  })
  names(liSample) = as.character(colNames)
  return(tbl_df(data.frame(liSample, check.names = FALSE)))
}

# create some sample data with the column name patterns required
weekDates = seq.Date(from = as.Date("2014-01-01"),
                     to = as.Date("2014-08-01"), by = "week")
dfTest = makeTable(weekDates, 10)

# test mutate on this table
dfTest %>% 
  mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
                          var = as.name(paste(as.character(weekDates), collapse =","))))

此处的预期输出是:

返回的内容
rowSums(dfTest[, as.character(weekDates)])

2 个答案:

答案 0 :(得分:5)

我认为这就是你所追求的目标

createSum = function(data, variableNames) {
    data %>% 
        mutate_(sumvar = paste(as.character(variableNames), collapse ="+"))
}
createSum(dfTest, weekDates)

我们只提供字符值而不是interp,因为您无法将名称列表作为单个参数传递给函数。另外,sum()会执行一些不希望的折叠,因为操作不是按行执行的,而是一次传递给矢量列。

此示例的另一个问题是您在data.frame中设置了check.names=FALSE,这意味着您创建的列名不能是有效符号。如果您愿意,可以在反向标记中明确包装变量名称

createSum(dfTest , paste0("`", weekDates,"`"))

但一般来说最好不要使用无效名称。

答案 1 :(得分:1)

我不知道这是否是“官方认可的”dplyr方式,但这是可能的:

weekDates = as.character(weekDates) # more convenient

dfTest %>% mutate(sumvar = Reduce(`+`, lapply(weekDates, get, .)))
#or
dfTest %>% mutate(sumvar = rowSums(as.data.frame(lapply(weekDates, get, .))))

这确实会带来潜在的重大性能损失,具体取决于您的特定用途 - 除dplyr定期复制整个数据外,我认为它还会在内部计算期间再次复制它。您可以查看data.table以避免通过添加列来进行额外复制(并使用.SDcols来避免第二个副本)+您将获得更好的语法。