使用数据框,我使用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)
这可以使用最新的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)
我们可以使用.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)
dplyr现在还为此提供了辅助函数(summarise_at,它接受参数vars,funs)
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)