2
votes

I need to do a diagonal multiplication for below table.

It's a 7*7 matrix:

  • Step 1: need a diagonal multiplcation for 7*7 matrix,
  • Step 2: then ignore the first column and select the next 7 columns and 7 rows and do diagonal multiplication.
  • Step 3: ignore the 1st & 2nd column and select the next 7 columns and 7 rows and do diagonal multiplication.
  • Step 4: similar to step 3 and increment the column ignore 1,2,3 .... and so on and so far ....

Note: the diagonal will be going in upward direct from right side Bottom to the left upper side.

Data:

28/02/2013  31/03/2013  30/04/2013  31/05/2013  30/06/2013  31/07/2013  31/08/2013  30/09/2013  31/10/2013  30/11/2013  31/12/2013  31/01/2014  28/02/2014
0.04        0.03        0.03        0.04        0.04        0.07        0.86        0.28            0.05        0.05        0.05        0.04        0.04
0.44        0.44        0.42        0.43        0.40        0.32        0.64        0.02        0.33        0.36        0.30        0.27        0.37
0.57        0.57        0.52        0.59        0.62        0.51        0.79        0.23        0.64        0.66        0.50        0.55        0.60
0.61        0.58        0.60        0.63        0.65        0.59        0.81        0.83        1.00        0.63        0.57        0.63        0.74
0.70        0.65        0.66        0.71        0.73        0.66        0.86        0.90        0.55        0.76        0.65        0.66        0.74
0.76        0.76        0.79        0.74        0.83        0.83        0.86        1.00        0.61        0.83        0.38        0.74        0.75
0.80        0.84        0.89        0.84        0.82        0.83        0.98        0.84        0.44        0.93        0.88        0.78        0.78

Considering each column as A, B, C, D, E, F, G, H, I, J, K and so on ... there will be many columns, but the number of rows will be only 7.

Calculation of the 7*7 daigonal matrix will be as follows.

A is result for -> STEP 1, B -> STEP 2 AND  C -> STEP 3 ... and so on.  

A                               B                                   C
G8*F7*E6*D5*C4*B3*A2  = 0.00    H8*G7*F6*E5*D4*C3*B2 = 0.02     I8*H7*G6*F5*E4*D3*C2 = 0.00
G8*F7*E6*D5*C4*B3  = 0.08       H8*G7*F6*E5*D4*C3 = 0.08        I8*H7*G6*F5*E4*D3 = 0.06
G8*F7*E6*D5*C4 = 0.19           H8*G7*F6*E5*D4 = 0.18           I8*H7*G6*F5*E4 = 0.14
G8*F7*E6*D5 = 0.37              H8*G7*F6*E5 = 0.31              I8*H7*G6*F5 = 0.22
G8*F8*E6 = 0.59                 H8*G7*F6 = 0.47                 I8*H7*G6 = 0.38
G8*F8 = 0.81                    H8*G7 = 0.72                    I8*H7 = 0.44
G8 = 0.98                       H8 = 0.84                       I8 = 0.44

So result should be printed as.

A         B     C
0       0.02    0.00
0.08    0.08    0.06
0.19    0.18    0.14
0.37    0.31    0.22
0.59    0.47    0.38
0.81    0.72    0.44
0.98    0.84    0.44

Similary there will result for D, E, F, and so on.

Please help, Thanks in Advance.

2
isnt this quite similar to your previous question stackoverflow.com/questions/44704224/… - can you maybe tweak that answer - user20650
i tried that code, but only working for first 7*7 matrix, but not working - moving forward, ignoring the 1st column and selecting the next 7 columns .... So can you please help me? - Prad
can i double check your data please: are you counting the date headers as row1 and why does G8*F7*E6*D5*C4*B3*A2 equal 0.00 - user20650
the date row is the header and i'm not counting it. G8*F7*E6*D5*C4*B3*A2 = 0.003231682 ..... this is what it gives, i just r-checked it. - Prad
@user - Did you deleted your answers? Please dont delete it, i would like to learn it, its always good to know how things can be written in different forms. Please provide the answers. - Prad

2 Answers

1
votes
sapply(lapply(7:NCOL(df), function(i)
    df[, (i-6):i]), function(a)
        round(x = rev(cumprod(rev(diag(as.matrix(a))))), digits = 2))
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#[1,] 0.00 0.00 0.00 0.00 0.00 0.00 0.00
#[2,] 0.09 0.08 0.06 0.08 0.08 0.03 0.00
#[3,] 0.19 0.18 0.14 0.21 0.26 0.05 0.15
#[4,] 0.37 0.31 0.22 0.41 0.33 0.23 0.24
#[5,] 0.59 0.48 0.38 0.51 0.40 0.23 0.38
#[6,] 0.81 0.72 0.44 0.57 0.73 0.30 0.58
#[7,] 0.98 0.84 0.44 0.93 0.88 0.78 0.78

Let me know if the output is correct

DATA

df = structure(list(A = c(0.04, 0.44, 0.57, 0.61, 0.7, 0.76, 0.8), 
    B = c(0.03, 0.44, 0.57, 0.58, 0.65, 0.76, 0.84), C = c(0.03, 
    0.42, 0.52, 0.6, 0.66, 0.79, 0.89), D = c(0.04, 0.43, 0.59, 
    0.63, 0.71, 0.74, 0.84), E = c(0.04, 0.4, 0.62, 0.65, 0.73, 
    0.83, 0.82), F = c(0.07, 0.32, 0.51, 0.59, 0.66, 0.83, 0.83
    ), G = c(0.86, 0.64, 0.79, 0.81, 0.86, 0.86, 0.98), H = c(0.28, 
    0.02, 0.23, 0.83, 0.9, 1, 0.84), I = c(0.05, 0.33, 0.64, 
    1, 0.55, 0.61, 0.44), J = c(0.05, 0.36, 0.66, 0.63, 0.76, 
    0.83, 0.93), K = c(0.05, 0.3, 0.5, 0.57, 0.65, 0.38, 0.88
    ), L = c(0.04, 0.27, 0.55, 0.63, 0.66, 0.74, 0.78), M = c(0.04, 
    0.37, 0.6, 0.74, 0.74, 0.75, 0.78)), .Names = c("A", "B", 
"C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"), class = "data.frame", row.names = c(NA, 
-7L))
1
votes

I think a for loop is a good bet here - inspired from this

n <- nrow(df)
b <- ncol(df) - n + 1
out <- matrix(0, n, b)

ro <- 1:n

for(i in 1:b){
  co <- i:(n + i - 1)
  out[ro, i] <- rev(cumprod(rev(df[cbind(ro, co)])))
}  

#             [,1]        [,2]        [,3]        [,4]       [,5]       [,6]
# [1,] 0.003423605 0.002303868 0.001785601 0.003374663 0.00337162 0.00232112
# [2,] 0.085590113 0.076795599 0.059520050 0.084366587 0.08429050 0.03315886
# [3,] 0.194522983 0.182846664 0.138418720 0.210916467 0.26340780 0.05181072
# [4,] 0.374082660 0.309909600 0.223256000 0.413561700 0.33342760 0.22526400
# [5,] 0.593782000 0.476784000 0.378400000 0.510570000 0.40172000 0.22526400
# [6,] 0.813400000 0.722400000 0.440000000 0.567300000 0.73040000 0.29640000
# [7,] 0.980000000 0.840000000 0.440000000 0.930000000 0.88000000 0.78000000

Wrap the answer in round to alter how it is printed.


Another way , also using indexing...

ro <- nrow(df)
co <- ncol(df)
b <- co - ro + 1
id <- pmin(ro, b)

ccols <- mapply(seq, 1:b, id:co)
rrows <- rep(1:ro, b)
mat <- matrix(rev(df[cbind(rrows, c(ccols))]), nr=ro)
matrix(rev(matrixStats::colCumprods(mat)), nr=ro) 

A quick benchmark on larger data seems to show that method two is considerably faster, however, if you convert the dataframe to a matrix then the for loop has similar speed