按列名分组并计算每列值的行总和

12

我有一个数据框,其中几列可能具有相同的名称。在这个小例子中,“A”和“G”列都出现了两次:

    A  C  G  A  G  T
1   1 NA NA NA  1 NA
2   1 NA  5  3  1 NA
3  NA  1 NA NA NA  1
4  NA NA  1  2 NA NA
5  NA NA  1  1 NA NA
6  NA  1 NA NA NA  1
7  NA  1 NA NA NA  1

我希望创建一个数据集,每个列名对应一列。对于每行,各个列的值应该被替换为该列名称内值的总和(sum(..., na.rm = TRUE))。例如,在第二行中,两个独立的“A”值(13)应该被替换为4。我不知道哪些列名会出现多次。
预期输出如下:
#     A  C  G  T
# 1   1  0  1  0
# 2   4  0  6  0
# 3   0  1  0  1
# 4   2  0  1  0
# 5   1  0  1  0
# 6   0  1  0  1
# 7   0  1  0  1

所以我想我可以做类似这样的事情:

noms = colnames(dat)
for(x in noms[duplicated(noms)]) {
  dat[ , x] = rowSums(dat[ , x == noms], na.rm = TRUE)
}
dat = dat[,!duplicated(noms)]

但这种方法有些笨拙,for循环本来就不太好用。有没有更简单的方法?

你想按行对具有相同名称的列进行求和吗? - David Arenburg
@DavidArenburg 是的,没错。 - user1356855
2个回答

18

我们可以转置dat,针对每个组计算原始datcolnamesrowsum,然后将结果再次转置回原始结构。

t(rowsum(t(dat), group = colnames(dat), na.rm = T))
#  A C G T
#1 1 0 1 0
#2 4 0 6 0
#3 0 1 0 1
#4 2 0 1 0
#5 1 0 1 0
#6 0 1 0 1
#7 0 1 0 1

3

我们可以使用split.default按名称拆分数据帧,并使用rowSums逐行求和,以创建每个唯一名称的一个列。

sapply(split.default(df, names(df)), rowSums, na.rm = TRUE)

#  A C G T
#1 1 0 1 0
#2 4 0 6 0
#3 0 1 0 1
#4 2 0 1 0
#5 1 0 1 0
#6 0 1 0 1
#7 0 1 0 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接