dplyr和非标准评估(NSE)

Tyl*_*uth 4 r dplyr

我正在尝试编写一个函数,它接受数据框的名称和列,以便使用dplyr进行汇总,然后返回汇总数据框.我已经尝试了lazyeval包中的一堆interp(),但是我花了太多时间试图让它工作.所以,我写了一个我想要的函数的"静态"版本:

summarize.df.static <- function(){
  temp_df <- mtcars %>%
    group_by(cyl) %>%
    summarize(qsec = mean(qsec),
              mpg=mean(mpg))
  return(temp_df)
}

new_df <- summarize.df.static()
head(new_df)
Run Code Online (Sandbox Code Playgroud)

这是我坚持的动态版本的开始:

summarize.df.dynamic <- function(df_in,sum_metric_in){
  temp_df <- df_in %>%
    group_by(cyl) %>%
    summarize_(qsec = mean(qsec),
              sum_metric_in=mean(sum_metric_in)) # some mix of interp()
  return(temp_df)
}

new_df <- summarize.df.dynamic(mtcars,"mpg")
head(new_df)
Run Code Online (Sandbox Code Playgroud)

请注意,我希望此示例中的列名称也来自传入的参数(在本例中为mpg).另请注意,qsec列是静态的,即不传入.

以下是"docendo discimus"发布的正确答案:

summarize.df.dynamic<- function(df_in, sum_metric_in){
  temp_df <- df_in %>%
    group_by(cyl) %>%
    summarize_(qsec = ~mean(qsec), 
               xyz = interp(~mean(var), var = as.name(sum_metric_in))) 

  names(temp_df)[names(temp_df) == "xyz"] <- sum_metric_in  
  return(temp_df)
}

new_df <- summarize.df.dynamic(mtcars,"mpg")
head(new_df)

#  cyl     qsec      mpg
#1   4 19.13727 26.66364
#2   6 17.97714 19.74286
#3   8 16.77214 15.10000

new_df <- summarize.df.dynamic(mtcars,"disp")
head(new_df)

#  cyl     qsec     disp
#1   4 19.13727 105.1364
#2   6 17.97714 183.3143
#3   8 16.77214 353.1000
Run Code Online (Sandbox Code Playgroud)

tal*_*lat 7

对于特定示例(使用静态"qsec"等),您可以执行以下操作:

library(dplyr)
library(lazyeval)
summarize.df <- function(data, sum_metric_in){
  data <- data %>%
    group_by(cyl) %>%
    summarize_(qsec = ~mean(qsec), 
               xyz = interp(~mean(var), var = as.name(sum_metric_in))) 

  names(data)[names(data) == "xyz"] <- sum_metric_in  
  data
}

summarize.df(mtcars, "mpg")
#Source: local data frame [3 x 3]
#
#  cyl     qsec      mpg
#1   4 19.13727 26.66364
#2   6 17.97714 19.74286
#3   8 16.77214 15.10000
Run Code Online (Sandbox Code Playgroud)

AFAIK你不能(还?)将输入"sum_metric_in"提供给dplyr :: rename,你通常会用它来重命名列,这就是为什么我在这个例子中做了不同的事情.

  • 你可以,但你需要使用`.dots`参数和`setNames()`来命名列表.这很痛苦:/ (3认同)