【问题标题】:How to sum over diagonals of data frame如何对数据框的对角线求和
【发布时间】:2015-04-29 23:47:34
【问题描述】:

假设我有这个数据框:

     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

【问题讨论】:

  • 这是矩阵还是data.frame? (矩阵更容易执行此操作)
  • data.frame,但将其转换为矩阵并返回到 data.frame,就像@Ben Bolker 的回答一样。

标签: r sum dataframe diagonal


【解决方案1】:

您可以使用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 在 cmets 中建议的那样)

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() 正常工作...

【讨论】:

  • 为了做到这一点,为什么需要将其转换为矩阵(而不是将其留在 data.frame 中)的逻辑是什么?
  • @BenBolker - row 和 col 适用于所有二维的“类矩阵”对象,包括。矩阵、data.frames、表格等
  • 另一个非常相似的:data.frame(vals = tapply(as.matrix(m), (LETTERS[row(m) + col(m)-1]), sum))
【解决方案2】:

另一个aggregate 变体,避免了公式界面,这实际上在这种情况下使事情复杂化:

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

【讨论】:

    【解决方案3】:

    使用 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 
    

    (不是你想要的格式,但也许没问题...)

    【讨论】:

    • 忘了说我的解决方案假设你设置了options(stringsAsFactors=FALSE)
    【解决方案4】:

    这是一个使用stack()aggregate() 的解决方案,尽管它要求第二个data.frame 包含字符向量,而不是因子(可以使用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
    

    【讨论】:

      猜你喜欢
      • 2021-09-17
      • 2021-11-08
      • 2018-06-20
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2015-02-04
      • 1970-01-01
      • 2022-11-18
      相关资源
      最近更新 更多