How to sum over diagonals of data frame

后端 未结 4 2434
温柔的废话
温柔的废话 2021-02-20 16:53

Say that I have this data frame:

     1   2   3   4      
100  8   12  5   14 
99   1   6   4   3   
98   2   5   4   11  
97   5   3   7   2   
<
相关标签:
4条回答
  • 2021-02-20 17:07

    You can use row() and col() to identify row/column relationships.

    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]))
    

    or (as suggested in comments by ?@thelatemail)

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

    or (@Frank)

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

    as.matrix() is required to make split() work correctly ...

    0 讨论(0)
  • 2021-02-20 17:09

    Here's a solution using stack(), and aggregate(), although it requires the second data.frame contain character vectors, as opposed to factors (could be forced with 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
    
    0 讨论(0)
  • 2021-02-20 17:15

    Another solution using bgoldst's definition of df1 and df2

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

    Gives

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

    (Not quite the format that you wanted, but maybe it's ok...)

    0 讨论(0)
  • 2021-02-20 17:30

    Another aggregate variation, avoiding the formula interface, which actually complicates matters in this instance:

    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
    
    0 讨论(0)
提交回复
热议问题