如何使用R在多列数据帧上运行tapply()?

Jot*_*ota 20 r data-manipulation

我有一个如下数据框:

a   b1  b2  b3  b4  b5  b6  b7  b8  b9
D   4   6   9   5   3   9   7   9   8
F   7   3   8   1   3   1   4   4   3
R   2   5   5   1   4   2   3   1   6
D   9   2   1   4   3   3   8   2   5
D   5   4   3   1   6   4   1   8   3
R   3   7   9   1   8   5   3   4   2
D   4   1   8   2   6   3   2   7   5
F   7   1   7   2   7   1   6   2   4
D   6   3   9   3   9   9   7   1   2
Run Code Online (Sandbox Code Playgroud)

该函数tapply(df[,2], INDEX = df$a, sum)可以很好地生成一个表,它以df [a]为单位对df [,2]中的所有内容求和,但是当我尝试tapply(df[,2:10], INDEX = df$a, sum)获取类似的表时,除了每列的总和(2,3,4,..., 10),我收到一条错误信息:

tapply错误(df [,2:10],INDEX = df $ a,sum):参数必须具有相同的长度

另外,我希望表的行名是列名df[,2:10],这样第1行是b1,第2行是b2,第9行是b9.

Jor*_*eys 19

这是因为tapply适用于向量,并将df [,2:10]转换为向量.接下来,sum将给出总和,而不是每列的总和.使用aggregate(),例如:

aggregate(df[,2:10],by=list(df$a), sum)
Run Code Online (Sandbox Code Playgroud)

如果要返回一个列表,可以使用by().确保指定colSums而不是sum,因为它适用于拆分的数据帧:

by(df[,2:10],df$a,FUN=colSums)
Run Code Online (Sandbox Code Playgroud)


Doo*_*gan 7

另一种可能性是结合applytapply.

apply(df[,-1], 2, function(x) tapply(x, df$a, sum))
Run Code Online (Sandbox Code Playgroud)

会产生输出(这是一个矩阵)

    b1  ...   b9
D   sD1 ...  sD9
F   sF1 ...  sF9
R   sR1 ...  sR9
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用as.data.frame()获取数据框作为输出.


Jot*_*ota 6

这是一种适用data.table于此问题的方法.

library(data.table)
DT <- data.table(df)
DT[, lapply(.SD, sum), by=a]
Run Code Online (Sandbox Code Playgroud)

这是一种dplyr方法

library(dplyr)
df %>% group_by(a) %>% summarise_all(funs(sum))
Run Code Online (Sandbox Code Playgroud)