dplyr - 使用列名作为函数参数

use*_*440 6 r dplyr

使用数据框,我使用dplyr来聚合某些列,如下所示.

> data <- data.frame(a=rep(1:2,3), b=c(6:11))
> data
  a  b
1 1  6
2 2  7
3 1  8
4 2  9
5 1 10
6 2 11
> data %>% group_by(a) %>% summarize(tot=sum(b))
# A tibble: 2 x 2
      a   tot
  <int> <int>
1     1    24
2     2    27
Run Code Online (Sandbox Code Playgroud)

太棒了.但是我想为此创建一个可重用的函数,以便可以将列名作为参数传递.

看看这里的相关问题的答案,我尝试了以下内容.

sumByColumn <- function(df, colName) {
  df %>%
  group_by(a) %>%
  summarize(tot=sum(colName))
  df
}
Run Code Online (Sandbox Code Playgroud)

但是我无法让它工作.

> sumByColumn(data, "b")

 Error in summarise_impl(.data, dots) : 
  Evaluation error: invalid 'type' (character) of argument. 

> sumByColumn(data, b)

 Error in summarise_impl(.data, dots) : 
  Evaluation error: object 'b' not found. 
> 
Run Code Online (Sandbox Code Playgroud)

And*_*own 13

我们可以用{{}}

library(dplyr)

sumByColumn <- function(df, colName) {
  df %>%
    group_by(a) %>%
    summarize(tot=sum({{colName}}))
}

sumByColumn(data, b)

#      a   tot
#  <int> <int>
#1     1    24
#2     2    27
Run Code Online (Sandbox Code Playgroud)


Lyz*_*deR 9

这可以使用最新的dplyr语法(可以在github上看到):

library(dplyr)
library(rlang)
sumByColumn <- function(df, colName) {
  df %>%
    group_by(a) %>%
    summarize(tot = sum(!! sym(colName)))
}

sumByColumn(data, "b")
## A tibble: 2 x 2
#      a   tot
#  <int> <int>
#1     1    24
#2     2    27
Run Code Online (Sandbox Code Playgroud)

另一种指定b为变量的方法:

library(dplyr)
sumByColumn <- function(df, colName) {
  myenc <- enquo(colName)
  df %>%
    group_by(a) %>%
    summarize(tot = sum(!!myenc))
}

sumByColumn(data, b)
## A tibble: 2 x 2
#      a   tot
#  <int> <int>
#1     1    24
#2     2    27
Run Code Online (Sandbox Code Playgroud)

  • 这是文档的一部分。而不是`!!`(这是一个方便的函数,它不适用于逻辑向量),而是使用`UQ`,这是正确的函数。即`过滤器(UQ(myenc)&gt; 7)`。然后它工作正常。 (2认同)

Ron*_*hah 6

我们可以使用.data代词。

library(dplyr)

sumByColumn <- function(df, colName) {
  df %>%
    group_by(a) %>%
    summarise(tot = sum(.data[[colName]]))
}

sumByColumn(data, "b")

#      a   tot
#* <int> <int>
#1     1    24
#2     2    27
Run Code Online (Sandbox Code Playgroud)


CPa*_*Pak 5

dplyr现在还为此提供了辅助函数(summarise_at,它接受参数varsfuns

sumByColumn <- function(df, colName) {
  df %>%
    group_by(a) %>%
    summarize_at(vars(colName), funs(tot = sum))
}
Run Code Online (Sandbox Code Playgroud)

提供相同的答案

# A tibble: 2 x 2
      # a   tot
  # <int> <int>
# 1     1    24
# 2     2    27
Run Code Online (Sandbox Code Playgroud)