动态dplyr列名计算

use*_*015 1 r dynamic dplyr

我有以下代码.

传入colName.我一直试图将它作为colName的值进行评估,但没有取得多大成功.我试过"eval","setNames"等.使用"_",仍然没有提供成功.

基本上,如果我的colName ="MyCol",我希望dplyr链执行,如同最后一行读取:

mutate(MyCol = ifelse(is.na(MyCol), "BLANK", MyCol))

makeSummaryTable <- function(colName,originalData){
  result <- originalData %>% 
    group_by_(colName) %>% 
    summarise(numObs = n()) %>% 
    ungroup() %>% 
    arrange(desc(numObs)) %>% 
    rowwise() %>% 
    mutate_(colName = ifelse(is.na(colName), "BLANK",colName))
  return(result)
}
Run Code Online (Sandbox Code Playgroud)

yee*_*dle 6

以下是如何使用dplyr 0.6.0使用新tidyeval方法进行非标准评估.(我不确定是否可以使用标准评估,至少以简单的方式):

library(dplyr)

makeSummaryTable <- function(colName, originalData){

  colName <- enquo(colName)

  originalData %>% 
    count(!!colName) %>% 
    arrange(desc(n)) %>%
    mutate(
      old_col = !!colName,
      !!quo_name(colName) := if_else(is.na(!!colName), "BLANK",!!colName)
      )
}

makeSummaryTable(hair_color, starwars)
#> # A tibble: 13 x 3
#>       hair_color     n       old_col
#>            <chr> <int>         <chr>
#>  1          none    37          none
#>  2         brown    18         brown
#>  3         black    13         black
#>  4         BLANK     5          <NA>
#>  5         white     4         white
#>  6         blond     3         blond
#>  7        auburn     1        auburn
#>  8  auburn, grey     1  auburn, grey
#>  9 auburn, white     1 auburn, white
#> 10        blonde     1        blonde
#> 11   brown, grey     1   brown, grey
#> 12          grey     1          grey
#> 13       unknown     1       unknown
Run Code Online (Sandbox Code Playgroud)

enquo将不带引号的列名称转换为一个名为quosure的奇特对象.!!然后取消引用quosure,以便它可以被评估,就好像它将直接在函数中输入一样.有关更深入和准确的解释,请参阅Hadley的"使用dplyr编程".

编辑:我意识到原来的问题是用用户提供的值命名新列,colName而不仅仅是colName我更新了我的答案.要实现这一点,需要将quosure转换为字符串(或标签)quo_name.然后,它可以被"不加引号"使用,!!就像常规的quosure一样.唯一要注意的是,由于R不能使头部或表达的尾部mutate(!!foo = bar),tidyeval引入了新的定义操作者:=(其可能是从为用户所熟悉data.table,其中它有一个稍微不同的使用).与传统的赋值运算符不同=,:=运算符允许在右侧和左侧进行取消引用.

(更新了使用NA其中一行中的数据框的答案,以说明最后一行mutate.我也使用了count代替group by+ summarize,我删除了不必要的rowwise.)