【问题标题】:dplyr: standard evaluation for mutate with quoted variable namesdplyr:对带引号的变量名进行变异的标准评估
【发布时间】:2015-05-07 17:37:55
【问题描述】:

我将如何使用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)])

【问题讨论】:

  • 您定义了makeTable ,然后调用makeDataFrame。这些应该是相同的功能吗?描述您对此示例输入的期望输出会很有帮助(为数据设置种子是可重现的)。
  • @MrFlick 谢谢。更改了函数名称。没有任何花哨的东西,只是所有变量名的变量中的sum 逐行传递给函数。将更新为预期的输出。

标签: r dplyr


【解决方案1】:

我想这就是你所追求的

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,"`"))

但通常最好不要使用无效名称。

【讨论】:

  • 谢谢,这样可以,但是如果函数没有方便的操作符怎么办?其次,我如何将参数列表按名称传递给函数中的...?我见过的唯一标准评估示例涉及一个变量名称。
  • 假设性不好说,每个功能可能都不一样。但是这种字符串构建方法应该适用于许多其他功能(sum 有点例外)。只是粘贴可能看起来像paste0("funname(", paste(vars, collapse=","), ")")
  • 是的,正如我所担心的那样,这看起来像糟糕的语法(这不是你的错!)。我不认为我很好地理解了这个范例——我想做的就是在data_frame 的环境中评估变量符号。当然有一种更简洁的方法可以做到这一点,而无需求助于繁琐的表达式构建或eval(parse(text =)。
  • 我以前研究过这个:stackoverflow.com/questions/28751023/…。我不确定您所设想的语法到底是什么,但大多数时候构建动态表达式并不是很漂亮。我同意评估已解析的字符串不是一个好主意,应尽可能避免。
【解决方案2】:

我不知道这是否是“官方认可的”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 来避免第二次复制)+ 可以说您会得到更好的语法。

【讨论】:

    猜你喜欢
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 1970-01-01
    • 2014-12-30
    相关资源
    最近更新 更多