Search code examples
rsumdata.tabledata-manipulationdiagonal

R sum diagonal left down to right top


I have a question about summing diagonal from left down to right top.

Here is the data (dt):

dt
     date       1       2       3         4
1: 2016-01-01  47   562358   2881713  6062886
2: 2016-02-01  37   667633   2868784  6033143
3: 2016-03-01 130   546816   2292909  5092588
4: 2016-04-01  60   453094   2277252  5276752

str(dt)
Classes ‘data.table’ and 'data.frame':  4 obs. of  5 variables:
 $ date  : chr  "2016-01-01" "2016-02-01" "2016-03-01" "2016-04-01" 
 $ 1     : num  47 37 130 60
 $ 2     : num  562358 667633 546816 453094 
 $ 3     : num  2881713 2868784 2292909 2277252 
 $ 4     : num  6062886 6033143 5092588 5276752 

What I want is to create like this:

NDate        Value
2016-01-01    47
2016-02-01    562395
2016-03-01    3549476
2016-04-01    8007158
2016-05-01    8779146
2016-06-01    7369840
2016-07-01    5276752

NDate is month of date plus col number. For example: NDate == 2016-02-01, it's Value is 562395, which is 37 + 562358.

How can I do?


Solution

  • 1) One can pass a two column matrix of i,j indexes to a data frame to get those value so:

    library(data.table)
    
    Sum <- function(i, d) sum(as.data.frame(d)[-1][cbind(1:i, i:1)])
    dt[, list(date, Value = sapply(1:.N, Sum, .SD))]
    

    giving:

             date   Value
    1: 2016-01-01      47
    2: 2016-02-01  562395
    3: 2016-03-01 3549476
    4: 2016-04-01 9478546
    

    2) Omitting date row number + column number is constant on anti-diagonals so:

    mat <- as.matrix(dt)[, -1]
    values <- tapply(mat, row(mat) + col(mat), sum)
    data.table(date = as.Date(dt$date[1]) + seq_along(values) - 1, values = values)
    

    giving:

             date  values
    1: 2016-01-01      47
    2: 2016-01-02  562395
    3: 2016-01-03 3549476
    4: 2016-01-04 9478546
    5: 2016-01-05 8779146
    6: 2016-01-06 7369840
    7: 2016-01-07 5276752
    

    Note

    The input in reproducible form is:

    Lines <- "date       1       2       3         4
    2016-01-01  47   562358   2881713  6062886
    2016-02-01  37   667633   2868784  6033143
    2016-03-01 130   546816   2292909  5092588
    2016-04-01  60   453094   2277252  5276752"
    
    library(data.table)
    dt <- fread(Lines, header = TRUE)