R 聚合大量的列
R aggregate by large number of columns
我有一个大约有 40 列的数据框 (df),我想使用其中 4 列的总和进行聚合。在我想要求和的 4 之外,第 1 列中的每个唯一值对应于其余列中的相同值,我想将所有列保留在聚合数据框中。有什么方法可以指定 by = list() 部分中的列,而不必显式键入它们?例如,如果我知道我想按第 1-36 列对 "field" 列求和。我试过了
aggregate(df$field, by = list(df[,1:36]), FUN = sum)
但它会抛出错误,因为那不是姓名列表。我也试过
aggregate(df$field, by = list(names(df)[1:36]), FUN = sum)
虽然这不会出错,但它会返回一个以我的 df 名称作为唯一观察值的聚合。
或者我错过了一个简单的表达方式 "aggregate these four columns using the rest of the data frame?"
谢谢
这是一个示例数据框:
A B C D Sum
1 A B C D 1
2 A B C D 2
3 A B C D 3
4 E F 1 R 4
5 E F 1 R 5
聚合后我希望它看起来像:
A B C D Sum
1 A B C D 6
2 E F 1 R 9
我知道如果我在聚合语句的 "by" 部分明确声明 x$A、x$B、x$C、x$D 就可以做到这一点,但在我的实际数据框中将需要明确键入大约 40 个字段名称。
您问的是如何聚合多个变量的总和,并按剩余变量分组。为此,我会先组合多个变量,然后使用(在我看来)更方便的 aggregate
函数公式界面进行聚合。例如,考虑根据剩余变量(Petal.Width 和物种)聚合鸢尾花数据集中 Sepal.Length、Sepal.Width 和 Petal.Length 的总和:
agg <- iris
cols <- c("Sepal.Length", "Sepal.Width", "Petal.Length")
agg$sum <- rowSums(agg[,cols])
agg <- agg[,!names(agg) %in% cols]
aggregate(sum~., data=agg, FUN=sum)
# Petal.Width Species sum
# 1 0.1 setosa 47.8
# 2 0.2 setosa 284.1
# 3 0.3 setosa 68.1
# 4 0.4 setosa 74.6
# 5 0.5 setosa 10.1
# 6 0.6 setosa 10.1
# 7 1.0 versicolor 79.9
# 8 1.1 versicolor 34.3
# 9 1.2 versicolor 63.8
# 10 1.3 versicolor 166.5
# 11 1.4 versicolor 96.7
# 12 1.5 versicolor 136.5
# 13 1.6 versicolor 42.0
# 14 1.7 versicolor 14.7
# 15 1.8 versicolor 13.9
# 16 1.4 virginica 14.3
# 17 1.5 virginica 27.4
# 18 1.6 virginica 16.0
# 19 1.7 virginica 11.9
# 20 1.8 virginica 162.2
# 21 1.9 virginica 71.7
# 22 2.0 virginica 91.3
# 23 2.1 virginica 94.4
# 24 2.2 virginica 48.3
# 25 2.3 virginica 125.6
# 26 2.4 virginica 44.4
# 27 2.5 virginica 48.2
使用@josilber 提到的示例数据,这将是使用 dplyr()
实现所需输出的另一种选择,这对于大型数据集更有效
library('dplyr')
out = agg %>%
regroup(lapply(names(select(agg, -sum)), as.symbol)) %>%
summarise_each(funs(sum))
Source: local data frame [27 x 3]
Groups: Species
# Species Petal.Width sum
#1 setosa 0.1 47.8
#2 setosa 0.2 284.1
#3 setosa 0.3 68.1
#4 setosa 0.4 74.6
#5 setosa 0.5 10.1
#6 setosa 0.6 10.1
#7 versicolor 1.0 79.9
#8 versicolor 1.1 34.3
#9 versicolor 1.2 63.8
#10 versicolor 1.3 166.5
#.. ... ... ...
使用data.table
library('data.table')
out = setDT(agg)[, list(sum = sum(sum)), by= names(agg[,!"sum", with=FALSE])]
# Species Petal.Width sum
#1: setosa 0.2 284.1
#2: setosa 0.4 74.6
#3: setosa 0.3 68.1
#4: setosa 0.1 47.8
#5: setosa 0.5 10.1
#6: setosa 0.6 10.1
#7: versicolor 1.4 96.7
#8: versicolor 1.5 136.5
#9: versicolor 1.3 166.5
#10:versicolor 1.6 42.0
# ...
像这样使用 data.frame 方法 (aggregate.data.frame
):
aggregate(df["field"], by = df[1:36], FUN = sum)
或者像这样使用公式方法 (aggregate.formula
):
nms <- c("field", names(df)[1:36])
aggregate(field ~., df, sum)
以问题末尾的示例数据而言:
Lines <- " A B C D Sum
1 A B C D 1
2 A B C D 2
3 A B C D 3
4 E F 1 R 4
5 E F 1 R 5"
df <- read.table(text = Lines, header = TRUE)
# data.frame method
aggregate(df["Sum"], df[1:4], sum)
# data.frame method - alternative
aggregate(df[5], df[-5], sum)
# formula method
aggregate(Sum ~., df, sum)
这将是 dplyr 的当前答案:
library('dplyr')
mytb<-read.table(text="
A B C D Sum
1 A B C D 1
2 A B C D 2
3 A B C D 3
4 E F 1 R 4
5 E F 1 R 5", header=T, stringsAsFactors=F)
mytb %>%
group_by_at(names(select(mytb, -"Sum") ) ) %>%
summarise_all(.funs=sum)
我有一个大约有 40 列的数据框 (df),我想使用其中 4 列的总和进行聚合。在我想要求和的 4 之外,第 1 列中的每个唯一值对应于其余列中的相同值,我想将所有列保留在聚合数据框中。有什么方法可以指定 by = list() 部分中的列,而不必显式键入它们?例如,如果我知道我想按第 1-36 列对 "field" 列求和。我试过了
aggregate(df$field, by = list(df[,1:36]), FUN = sum)
但它会抛出错误,因为那不是姓名列表。我也试过
aggregate(df$field, by = list(names(df)[1:36]), FUN = sum)
虽然这不会出错,但它会返回一个以我的 df 名称作为唯一观察值的聚合。
或者我错过了一个简单的表达方式 "aggregate these four columns using the rest of the data frame?"
谢谢
这是一个示例数据框:
A B C D Sum
1 A B C D 1
2 A B C D 2
3 A B C D 3
4 E F 1 R 4
5 E F 1 R 5
聚合后我希望它看起来像:
A B C D Sum
1 A B C D 6
2 E F 1 R 9
我知道如果我在聚合语句的 "by" 部分明确声明 x$A、x$B、x$C、x$D 就可以做到这一点,但在我的实际数据框中将需要明确键入大约 40 个字段名称。
您问的是如何聚合多个变量的总和,并按剩余变量分组。为此,我会先组合多个变量,然后使用(在我看来)更方便的 aggregate
函数公式界面进行聚合。例如,考虑根据剩余变量(Petal.Width 和物种)聚合鸢尾花数据集中 Sepal.Length、Sepal.Width 和 Petal.Length 的总和:
agg <- iris
cols <- c("Sepal.Length", "Sepal.Width", "Petal.Length")
agg$sum <- rowSums(agg[,cols])
agg <- agg[,!names(agg) %in% cols]
aggregate(sum~., data=agg, FUN=sum)
# Petal.Width Species sum
# 1 0.1 setosa 47.8
# 2 0.2 setosa 284.1
# 3 0.3 setosa 68.1
# 4 0.4 setosa 74.6
# 5 0.5 setosa 10.1
# 6 0.6 setosa 10.1
# 7 1.0 versicolor 79.9
# 8 1.1 versicolor 34.3
# 9 1.2 versicolor 63.8
# 10 1.3 versicolor 166.5
# 11 1.4 versicolor 96.7
# 12 1.5 versicolor 136.5
# 13 1.6 versicolor 42.0
# 14 1.7 versicolor 14.7
# 15 1.8 versicolor 13.9
# 16 1.4 virginica 14.3
# 17 1.5 virginica 27.4
# 18 1.6 virginica 16.0
# 19 1.7 virginica 11.9
# 20 1.8 virginica 162.2
# 21 1.9 virginica 71.7
# 22 2.0 virginica 91.3
# 23 2.1 virginica 94.4
# 24 2.2 virginica 48.3
# 25 2.3 virginica 125.6
# 26 2.4 virginica 44.4
# 27 2.5 virginica 48.2
使用@josilber 提到的示例数据,这将是使用 dplyr()
实现所需输出的另一种选择,这对于大型数据集更有效
library('dplyr')
out = agg %>%
regroup(lapply(names(select(agg, -sum)), as.symbol)) %>%
summarise_each(funs(sum))
Source: local data frame [27 x 3]
Groups: Species
# Species Petal.Width sum
#1 setosa 0.1 47.8
#2 setosa 0.2 284.1
#3 setosa 0.3 68.1
#4 setosa 0.4 74.6
#5 setosa 0.5 10.1
#6 setosa 0.6 10.1
#7 versicolor 1.0 79.9
#8 versicolor 1.1 34.3
#9 versicolor 1.2 63.8
#10 versicolor 1.3 166.5
#.. ... ... ...
使用data.table
library('data.table')
out = setDT(agg)[, list(sum = sum(sum)), by= names(agg[,!"sum", with=FALSE])]
# Species Petal.Width sum
#1: setosa 0.2 284.1
#2: setosa 0.4 74.6
#3: setosa 0.3 68.1
#4: setosa 0.1 47.8
#5: setosa 0.5 10.1
#6: setosa 0.6 10.1
#7: versicolor 1.4 96.7
#8: versicolor 1.5 136.5
#9: versicolor 1.3 166.5
#10:versicolor 1.6 42.0
# ...
像这样使用 data.frame 方法 (aggregate.data.frame
):
aggregate(df["field"], by = df[1:36], FUN = sum)
或者像这样使用公式方法 (aggregate.formula
):
nms <- c("field", names(df)[1:36])
aggregate(field ~., df, sum)
以问题末尾的示例数据而言:
Lines <- " A B C D Sum
1 A B C D 1
2 A B C D 2
3 A B C D 3
4 E F 1 R 4
5 E F 1 R 5"
df <- read.table(text = Lines, header = TRUE)
# data.frame method
aggregate(df["Sum"], df[1:4], sum)
# data.frame method - alternative
aggregate(df[5], df[-5], sum)
# formula method
aggregate(Sum ~., df, sum)
这将是 dplyr 的当前答案:
library('dplyr')
mytb<-read.table(text="
A B C D Sum
1 A B C D 1
2 A B C D 2
3 A B C D 3
4 E F 1 R 4
5 E F 1 R 5", header=T, stringsAsFactors=F)
mytb %>%
group_by_at(names(select(mytb, -"Sum") ) ) %>%
summarise_all(.funs=sum)