我有一个关于在R中聚合值的简单问题。
假设我有一个数据帧:
DF <- data.frame(col1=c("Type 1", "Type 1B", "Type 2"), col2=c(1, 2, 3))
看起来像这样:
col1 col2
1 Type 1 1
2 Type 1B 2
3 Type 2 3
我注意到数据中有Type 1
和Type 1B
,因此我想将Type 1B
合并到Type 1
中。
所以我决定使用dplyr
:
filter(DF, col1=='Type 1' | col1=='Type 1B') %>%
summarise(n = sum(col2))
但现在我需要坚持下去:
DF2 <- data.frame('Type 1', filter(DF, col1=='Type 1' | col1=='Type 1B') %>%
summarise(n = sum(col2)))
我想我想cbind
这个新的DF2回到原来的DF,但这意味着我必须将列名设置为一致:
names(DF2) <- c('col1', 'col2')
好的,现在我可以回复:
rbind(DF2, DF[3,])
结果呢?它起作用....
col1 col2
1 Type 1 3
3 Type 2 3
......但是唉!太糟糕了!必须有一种更好的方法来简单地组合价值观。
答案 0 :(得分:4)
这是一种可能的dplyr方法:
library(dplyr)
DF %>%
group_by(col1 = sub("(.*\\d+).*$", "\\1", col1)) %>%
summarise(col2 = sum(col2))
#Source: local data frame [2 x 2]
#
# col1 col2
#1 Type 1 3
#2 Type 2 3
答案 1 :(得分:4)
将sub()
与aggregate()
一起使用,从col1
的末尾删除除数字以外的任何内容,
do.call("data.frame",
aggregate(col2 ~ cbind(col1 = sub("\\D+$", "", col1)), DF, sum)
)
# col1 col2
# 1 Type 1 3
# 2 Type 2 3
do.call()
包装器在那里,以便aggregate()
之后的第一列从矩阵正确地更改为向量。这样,以后就不会有任何意外。
答案 2 :(得分:2)
您可以尝试:
library(data.table)
setDT(transform(DF, col1=gsub("(.*)[A-Z]+$","\\1",DF$col1)))[,list(col2=sum(col2)),col1]
# col1 col2
# 1: Type 1 3
# 2: Type 2 3
甚至更直接:
setDT(DF)[, .(col2 = sum(col2)), by = .(col1 = sub("[[:alpha:]]+$", "", col1))]
答案 3 :(得分:1)
在我看来,aggregate()
是完成此功能的完美功能,但您不应该进行任何文字处理(例如gsub()
)。我会分两步完成这个过程:
col1
。col1
计算聚合以指定分组。DF$col1 <- ifelse(DF$col1 %in% c('Type 1','Type 1B'),'Type 1',levels(DF$col1));
DF;
## col1 col2
## 1 Type 1 1
## 2 Type 1 2
## 3 Type 2 3
DF <- aggregate(col2~col1, DF, FUN=sum );
DF;
## col1 col2
## 1 Type 1 3
## 2 Type 2 3