我有一个包含约200列的数据框,其中我想按前10个因子进行分组,并求其余列的总和。
我有要分组的所有列名列表和要聚合的所有列列表。
我需要的输出格式是相同的数据框,具有相同数量的列,只是已经分组在一起了。
是否可以使用data.table
、plyr
或其他任何包来解决问题?
我有一个包含约200列的数据框,其中我想按前10个因子进行分组,并求其余列的总和。
我有要分组的所有列名列表和要聚合的所有列列表。
我需要的输出格式是相同的数据框,具有相同数量的列,只是已经分组在一起了。
是否可以使用data.table
、plyr
或其他任何包来解决问题?
data.table 的方式是:
DT[, lapply(.SD,sum), by=list(col1,col2,col3,...)]
或者DT[, lapply(.SD,sum), by=colnames(DT)[1:10]]
其中.SD
是(D)ata的子集,不包括组列。(顺便说一下:如果你需要泛指组列,它们在.BY
中。)
请看下面使用dplyr::across的更现代化的回答。
dplyr
的方法是:
library(dplyr)
df %>%
group_by(col1, col2, col3) %>%
summarise_each(funs(sum))
您可以使用在?dplyr::select
的帮助文件中提到的特殊函数进一步指定要汇总或排除的列,以便使用summarise_each
。
在基础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)
(您可以使用paste函数构造公式并使用formula
)
这似乎是使用ddply的一个任务(我使用包含在plyr中的“baseball”数据集):
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)