循环对角乘法——7*7矩阵……等等

Loop diagonal multiplication - 7 * 7 matrix ... and so on

我需要对下面的 table 进行对角乘法。

这是一个7*7的矩阵:

注意:对角线将从右下角到左上角直接向上

数据:

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

假设每列为A、B、C、D、E、F、G、H、I、J、K等……列数会很多,但行数只有7.

7*7对角矩阵的计算如下。

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

因此结果应打印为。

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

D、E、F 等也会有类似的结果。

请帮助,在此先感谢。

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

让我知道输出是否正确

数据

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

我认为 for 循环是一个不错的选择 - 灵感来自 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

将答案包裹在 round 中以改变它的打印方式。


另一种方式,同样使用索引...

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) 

对较大数据的快速基准测试似乎表明方法二要快得多,但是,如果将数据帧转换为矩阵,则 for 循环具有相似的速度