Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sum over diagonals of data frame

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   

In this above data frame, the values indicate counts of how many observations take on (100, 1), (99, 1), etc.

In my context, the diagonals have the same meanings:

     1   2   3   4
100  A   B   C   D 
99   B   C   D   E  
98   C   D   E   F 
97   D   E   F   G

How would I sum across the diagonals (i.e., sum the counts of the like letters) in the first data frame?

This would produce:

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

For example, D is 5+5+4+14

like image 252
bill999 Avatar asked Apr 29 '15 23:04

bill999


People also ask

How do you sum across rows in a data frame?

To sum all the rows of a DataFrame, use the sum() function and set the axis value as 1. The value axis 1 will add the row values.

How do you add a total to a data frame?

To get the total or sum of a column use sum() method, and to add the result of the sum as a row to the DataFrame use loc[] , at[] , append() and pandas. Series() methods.


1 Answers

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 ...

like image 142
Ben Bolker Avatar answered Oct 26 '22 11:10

Ben Bolker