R dplyr对仅以其字符串名称

时间:2017-09-19 21:39:12

标签: r dynamic dplyr quoting rlang

我正在使用R中的dplyr进行编程,以便对数据帧的列进行操作,这些列只能通过字符串名称来识别。我知道最近有一个dplyr的更新来支持quouts等等,我在这里回顾了我认为新的“使用dplyr编程”文章的相关组件:http://dplyr.tidyverse.org/articles/programming.html。但是,我仍然无法做我想做的事。

我的情况是我只通过其字符串名称知道数据框的列名。因此,我不能在函数内调用dplyr时使用非标准评估,甚至不能在运行之间列名可能会更改的脚本中使用非标准评估,因为我无法硬编码未加引号(即“裸” “)列名一般。我想知道如何解决这个问题,我猜我用新的引用/取消引用语法忽略了一些东西。

例如,假设我有用户输入来定义数据分布的截止百分位数。用户可以使用他/她想要的任何百分位来运行代码,并且他/她选择的百分位将改变输出。在分析中,使用所使用的百分位名称创建中间数据框中的列;因此,该列的名称会根据用户输入的截止百分位数而变化。

下面是一个简单的例子来说明。我想用截止百分位数的各种值来调用函数。我希望名为MPGCutoffs的数据框具有一个根据所选截止分位数命名的列(这当前在下面的代码中有效),我想稍后对此列名进行操作。由于这个列名的一般性,我只能在编写函数时根据输入pctCutoff知道它,所以当只知道{probColName定义的字符串时,我需要一种方法来操作它。 1}},它遵循基于pctCutoff的值的预定义模式。

userInput_prob1 <- 0.95
userInput_prob2 <- 0.9

# Function to get cars that have the "best" MPG
# fuel economy, where "best" is defined by the
# percentile cutoff passed to the function.
getBestMPG <- function( pctCutoff ){

  # Define new column name to hold the MPG percentile cutoff.
  probColName <- paste0('P', pctCutoff*100)

  # Compute the MPG percentile cutoff by number of gears.
  MPGCutoffs <- mtcars %>%
    dplyr::group_by( gear ) %>%
    dplyr::summarize( !!probColName := quantile(mpg, pctCutoff) )

  # Filter mtcars with only MPG values above cutoffs.
  output <- mtcars %>%
    dplyr::left_join( MPGCutoffs, by='gear' ) %>%
    dplyr::filter( mpg > !!probColName ) #****This doesn't run; this is where I'm stuck

  # Return filtered data.
  return(output)
}

best_1 <- getBestMPG( userInput_prob1 )
best_2 <- getBestMPG( userInput_prob2 )

dplyr::filter()语句是我无法正常运行的。我试过了:

dplyr::filter( mpg > probColName ) - 没有错误,但没有返回任何行。

dplyr::filter( mpg > !!probColName ) - 没有错误,但没有返回任何行。

我也看过一些示例,我可以将quo(P95)之类的内容传递给函数,然后在调用dplyr::filter()时取消引用它;我已经得到了这个,但它并没有解决我的问题,因为它需要在函数外部对变量名进行硬编码。例如,如果我执行此操作并且用户传递的百分位数为0.90,则对dplyr::filter()的调用将失败,因为创建的列名为P90而不是P95

非常感谢任何帮助。我希望有一个简单的解决方案,我只是忽略了。

2 个答案:

答案 0 :(得分:8)

如果你在一个字符串(也就是字符向量)中有一个列名,并且你想将它与tidyeval一起使用,那么你可以用rlang::sym()来转换它。只需改变

dplyr::filter( mpg > !!rlang::sym(probColName) )

它应该有效。这取自此github问题的建议:https://github.com/tidyverse/rlang/issues/116

使用

仍然可以
dplyr::summarize( !!probColName := quantile(mpg, pctCutoff) )

因为在动态设置参数名称时,您只需要字符串而不是未标记的符号。

答案 1 :(得分:2)

这是Hadley在MrFlick的回答(https://github.com/tidyverse/rlang/issues/116)中提到的帖子中的另一种解决方案。使用基础R中的as.name()代替rlang::sym(),您仍然需要取消引用它。也就是说,以下内容也有效:

dplyr::filter( mpg > !!as.name(probColName) )

相关问题