3

我正在努力使用dplyrR 中的编程来操作数据框的列,这些列仅由它们的字符串名称知道。我知道最近有一个更新来dplyr支持 quosures 等,我在这里回顾了我认为新的“使用 dplyr 编程”文章的相关组件:http: //dplyr.tidyverse.org/articles/programming .html。但是,我仍然无法做我想做的事。

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

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

下面是一个最小的例子来说明。我想用截止百分位数的各种值调用该函数。我希望命名的数据框MPGCutoffs有一个根据所选截止分位数命名的列(这目前在下面的代码中有效),并且我想稍后对该列名进行操作。由于这个列名的普遍性,我在pctCutoff写函数的时候只能从输入的角度知道,所以我需要一种方法在只知道定义的字符串的情况下对其进行操作probColName,它遵循基于预定义的模式关于 的值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()失败,因为创建的列是 namedP90而不是P95

任何帮助将不胜感激。我希望有一个简单的解决方案,我只是忽略了。

4

2 回答 2

9

如果您在字符串(又名字符向量)中有一个列名,并且您想将它与 tidyeval 一起使用,那么您可以使用rlang::sym(). 只是改变

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

它应该可以工作。这取自此 github 问题的建议:https ://github.com/tidyverse/rlang/issues/116

用起来还是不错的

dplyr::summarize( !!probColName := quantile(mpg, pctCutoff) )

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

于 2017-09-19T21:44:45.973 回答
3

这是哈德利在 MrFlick 的回答( https://github.com/tidyverse/rlang/issues/116)中提到的帖子中的评论的替代解决方案。使用as.name()from base R 代替rlang::sym(),您仍然需要取消引用它。也就是说,以下也有效:

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

于 2017-09-19T22:17:42.780 回答