R由大量列聚合

时间:2015-06-05 15:02:52

标签: r aggregate

我有一个大约有40列的数据框(df),我希望使用4列的总和来聚合。在我想要求和的4之外,第1列中的每个唯一值对应于其余列中的相同值,并且我希望将所有列保留在聚合数据框中。有没有什么办法可以指定by = list()部分中的列而不必显式地键入它们?例如,如果我知道我想要对列"字段"第1-36列。我试过了

aggregate(df$field, by = list(df[,1:36]), FUN = sum)

但它会抛出一个错误,因为它不是一个名字列表。我也试过了

aggregate(df$field, by = list(names(df)[1:36]), FUN = sum)

虽然这并没有给出错误,但它给了我一个聚合,我的df名称作为独特的观察结果。

或者我错过了一种简单的说法"使用数据框的其余部分聚合这四列?"

由于

这是一个示例数据框:

  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个字段名称。

4 个答案:

答案 0 :(得分:4)

您正在询问如何汇总多个变量的总和,并按剩余变量分组。我会先将多个变量组合起来,然后使用(在我看来)aggregate函数更方便的公式接口进行聚合。例如,考虑根据剩余变量(Petal.Width和Species)在虹膜数据集中聚合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

答案 1 :(得分:3)

使用@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
# ...

答案 2 :(得分:2)

使用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)

答案 3 :(得分:0)

这将是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)