按组对名称以模式开头的所有列求和
Sum all columns whose names start with a pattern, by group
我是 R 的新手,我正在尝试根据名称按组对列求和。我有一个这样的数据框:
DT <- data.frame(a011=c(0,10,20,0),a012=c(010,10,0,0),a013=c(10,30,0,10),
a021=c(10,20,20,10),a022=c(0,0,0,10),a023=c(20,0,0,0),a031=c(30,0,10,0),
a032=c(0,0,10,0),a033=c(20,0,0,0))
我想获得所有以 "a01" 开头的列的总和,所有以 "a02" 开头的列的总和以及所有以 "a03" 开头的列的总和:
a01tot a02tot a03tot
20 30 50
50 20 0
20 20 20
10 20 0
到目前为止我用过[=15=]
DT$a01tot <- rowSums(DT[,grep("a01", names(DT))])
等等,但我的真实数据框有更多组,我想避免为每个组编写一行代码。我想知道是否可以在向量或列表中包含 "a01"、"a02"、"a03"... 并添加列 "a01tot"、"a02tot","a03tot"...自动添加到数据框。
我知道我的问题与这个问题非常相似:,但是那里指出的解决方案,
cbind(df, t(rowsum(t(df), sub("_.*", "_t", names(df)))))
在我的情况下不起作用,因为没有要替换的公共元素(如“_”)(我无法将变量的名称更改为 a01_1、a02_2 等。 ).
切换到 "long" 格式对我来说也不是一个可行的解决方案。
任何帮助将不胜感激。
您可以将模式存储在向量中并循环遍历它们。在你的例子中,你可以使用这样的东西:
patterns <- unique(substr(names(DT), 1, 3)) # store patterns in a vector
new <- sapply(patterns, function(xx) rowSums(DT[,grep(xx, names(DT)), drop=FALSE])) # loop through
# a01 a02 a03
#[1,] 20 30 50
#[2,] 50 20 0
#[3,] 20 20 20
#[4,] 10 20 0
您可以这样调整名称:
colnames(new) <- paste0(colnames(new), "tot") # rename
另一种可能的解决方案
library(dplyr)
library(reshape2)
library(tidyr)
DT %>%
mutate(id = 1:n()) %>%
melt(id.vars = c('id')) %>%
mutate(Group = substr(variable, 1, 3)) %>%
group_by(id, Group) %>%
summarise(tot = sum(value)) %>%
spread(Group, tot) %>%
select(-id)
结果
Source: local data frame [4 x 3]
a01 a02 a03
1 20 30 50
2 50 20 0
3 20 20 20
4 10 20 0
然后按照@Jota 的建议colnames(new) <- paste0(colnames(new), "tot")
我是 R 的新手,我正在尝试根据名称按组对列求和。我有一个这样的数据框:
DT <- data.frame(a011=c(0,10,20,0),a012=c(010,10,0,0),a013=c(10,30,0,10),
a021=c(10,20,20,10),a022=c(0,0,0,10),a023=c(20,0,0,0),a031=c(30,0,10,0),
a032=c(0,0,10,0),a033=c(20,0,0,0))
我想获得所有以 "a01" 开头的列的总和,所有以 "a02" 开头的列的总和以及所有以 "a03" 开头的列的总和:
a01tot a02tot a03tot
20 30 50
50 20 0
20 20 20
10 20 0
到目前为止我用过[=15=]
DT$a01tot <- rowSums(DT[,grep("a01", names(DT))])
等等,但我的真实数据框有更多组,我想避免为每个组编写一行代码。我想知道是否可以在向量或列表中包含 "a01"、"a02"、"a03"... 并添加列 "a01tot"、"a02tot","a03tot"...自动添加到数据框。
我知道我的问题与这个问题非常相似:
cbind(df, t(rowsum(t(df), sub("_.*", "_t", names(df)))))
在我的情况下不起作用,因为没有要替换的公共元素(如“_”)(我无法将变量的名称更改为 a01_1、a02_2 等。 ).
切换到 "long" 格式对我来说也不是一个可行的解决方案。
任何帮助将不胜感激。
您可以将模式存储在向量中并循环遍历它们。在你的例子中,你可以使用这样的东西:
patterns <- unique(substr(names(DT), 1, 3)) # store patterns in a vector
new <- sapply(patterns, function(xx) rowSums(DT[,grep(xx, names(DT)), drop=FALSE])) # loop through
# a01 a02 a03
#[1,] 20 30 50
#[2,] 50 20 0
#[3,] 20 20 20
#[4,] 10 20 0
您可以这样调整名称:
colnames(new) <- paste0(colnames(new), "tot") # rename
另一种可能的解决方案
library(dplyr)
library(reshape2)
library(tidyr)
DT %>%
mutate(id = 1:n()) %>%
melt(id.vars = c('id')) %>%
mutate(Group = substr(variable, 1, 3)) %>%
group_by(id, Group) %>%
summarise(tot = sum(value)) %>%
spread(Group, tot) %>%
select(-id)
结果
Source: local data frame [4 x 3]
a01 a02 a03
1 20 30 50
2 50 20 0
3 20 20 20
4 10 20 0
然后按照@Jota 的建议colnames(new) <- paste0(colnames(new), "tot")