如何对数据框的对角线求和

10

假设我有这样的数据框:

     1   2   3   4      
100  8   12  5   14 
99   1   6   4   3   
98   2   5   4   11  
97   5   3   7   2   
在这个数据框中,值表示观察值采取(100, 1)、(99, 1)等的计数。

在我的语境中,对角线具有相同的含义。
     1   2   3   4
100  A   B   C   D 
99   B   C   D   E  
98   C   D   E   F 
97   D   E   F   G

我该如何对第一个数据框的对角线进行求和(即,将相同字母的计数相加)?

这将产生以下结果:

group  sum
A      8
B      13
C      13
D      28
E      10
F      18
G      2
例如,D5+5+4+14

这是一个矩阵还是数据框?(在矩阵上执行此操作更容易) - David Robinson
data.frame,但是像@Ben Bolker的回答中将其转换为矩阵,再转换回data.frame就可以解决问题。 - bill999
类似:https://dev59.com/z14c5IYBdhLWcg3wa52M - Frank
4个回答

18

您可以使用row()col()来确定行/列关系。

m <- read.table(text="
    1   2   3   4      
100  8   12  5   14 
99   1   6   4   3   
98   2   5   4   11  
97   5   3   7   2")

vals <- sapply(2:8,
       function(j) sum(m[row(m)+col(m)==j]))

或者(正如?@thelatemail在评论中建议的那样)

vals <- sapply(split(as.matrix(m), row(m) + col(m)), sum)
data.frame(group=LETTERS[seq_along(vals)],sum=vals)

或者(@Frank)

data.frame(vals = tapply(as.matrix(m), 
       (LETTERS[row(m) + col(m)-1]), sum))

as.matrix() 是必需的,以便使 split() 正常工作 ...


为什么需要将数据转换成矩阵(而不是保留在数据框中)才能实现这个功能的逻辑是什么? - bill999
2
@BenBolker - row和col适用于所有具有2个维度的“类矩阵”对象,包括矩阵、数据框、表格等。 - thelatemail
1
另一个非常相似的例子:data.frame(vals = tapply(as.matrix(m), (LETTERS[row(m) + col(m)-1]), sum)) - Jota

7
另一种聚合变体,避免使用公式接口,在这种情况下实际上会使问题更加复杂:
aggregate(list(Sum=unlist(dat)), list(Group=LETTERS[c(row(dat) + col(dat))-1]), FUN=sum)

#  Group Sum
#1     A   8
#2     B  13
#3     C  13
#4     D  28
#5     E  10
#6     F  18
#7     G   2

6

另一种解决方案是使用bgoldst对df1df2的定义。

sapply(unique(c(as.matrix(df2))),
       function(x) sum(df1[df2 == x]))

提供

#A  B  C  D  E  F  G 
#8 13 13 28 10 18  2 

(虽然不完全符合您想要的格式,但也许可以……)


1
忘了提到我的解决方案假设您已经设置了 options(stringsAsFactors=FALSE) - cryo111

5

以下是使用stack()aggregate()的解决方案,但需要第二个数据框包含字符向量,而不是因子(可以使用lapply(df2,as.character)强制转换):

df1 <- data.frame(a=c(8,1,2,5), b=c(12,6,5,3), c=c(5,4,4,7), d=c(14,3,11,2) );
df2 <- data.frame(a=c('A','B','C','D'), b=c('B','C','D','E'), c=c('C','D','E','F'), d=c('D','E','F','G'), stringsAsFactors=F );
aggregate(sum~group,data.frame(sum=stack(df1)[,1],group=stack(df2)[,1]),sum);
##   group sum
## 1     A   8
## 2     B  13
## 3     C  13
## 4     D  28
## 5     E  10
## 6     F  18
## 7     G   2

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