我有一个大约有 200 列的数据框,我想按其中的前 10 列对表格进行分组,这些列是因子,并对其余列进行求和。
我有我想要分组的所有列名称的列表以及我想要聚合的所有列的列表。
我正在寻找的输出格式需要是具有相同数量列的相同数据帧,只是分组在一起。
有没有使用包
data.table
、plyr
或任何其他包的解决方案?
请参阅下面使用
dplyr::across
的更现代答案。
dplyr
方式是:
library(dplyr)
df %>%
group_by(col1, col2, col3) %>%
summarise_each(funs(sum))
您可以使用
summarise_each
帮助文件中提到的特殊功能进一步指定要从?dplyr::select
中汇总或排除的列。
data.table方式是:
DT[, lapply(.SD,sum), by=list(col1,col2,col3,...)]
或
DT[, lapply(.SD,sum), by=colnames(DT)[1:10]]
其中
.SD
是 (D)ata 不包括组列的 (S) 子集。 (旁白:如果您需要一般性地引用组列,它们位于 .BY
中。)
在基础 R 中,这将是...
aggregate( as.matrix(df[,11:200]), as.list(df[,1:10]), FUN = sum)
编辑: 自从我写这篇文章以来,聚合函数已经取得了长足的进步。上面的铸造都不是必要的。
aggregate( df[,11:200], df[,1:10], FUN = sum )
有很多种写法。假设前 10 列被命名为
a1
到 a10
我喜欢下面的内容,尽管它很冗长。
aggregate(. ~ a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10, data = dat, FUN = sum)
(您可以使用粘贴来构造公式并使用
formula
)
这似乎是 ddply 的任务(我使用 plyr 中包含的“棒球”数据集):
library(plyr)
groupColumns = c("year","team")
dataColumns = c("hr", "rbi","sb")
res = ddply(baseball, groupColumns, function(x) colSums(x[dataColumns]))
head(res)
这为每个 groupColumns 提供了 dataColumns 中指定的列的总和。
使用 plyr::ddply:
library(plyr)
ddply(dtfr, .(name1, name2, namex), numcolwise(sum))
让我们考虑这个例子:
df <- data.frame(a = 'a', b = c('a', 'a', 'b', 'b', 'b'), c = 1:5, d = 11:15,
stringsAsFactors = TRUE)
更新
dplyr
1.1.0 及以上
您可以使用
pick
选择列 -
df %>%
group_by(pick(where(is.factor))) %>%
summarise(across(everything(), sum))
或者使用
.by
参数。
df %>% summarise(across(everything(), sum), .by = where(is.factor))
之前
dplyr
1.1.0
_all
、_at
和 _if
动词现已被取代,我们现在使用 across
对所有因子列进行分组并对所有其他列求和,我们可以这样做:
library(dplyr)
df %>%
group_by(across(where(is.factor))) %>%
summarise(across(everything(), sum))
# a b c d
# <fct> <fct> <int> <int>
#1 a a 3 23
#2 a b 12 42
对所有因子列和总和数字列进行分组:
df %>%
group_by(across(where(is.factor))) %>%
summarise(across(where(is.numeric), sum))
我们也可以按位置执行此操作,但必须注意数字,因为它不计算分组列。
df %>% group_by(across(1:2)) %>% summarise(across(1:2, sum))
使用 dplyr 执行此操作的另一种通用方法(不需要列列表)是:
df %>% group_by_if(is.factor) %>% summarize_if(is.numeric,sum,na.rm = TRUE)