我应该使用什么方法来通过if语句优化此嵌套的for循环?

时间:2019-03-27 18:44:54

标签: r for-loop optimization apply

我正在使用R运行100,000个仿真,并且此代码块是仿真过程的一部分。我知道R对于for循环不是很友好,因此我想使用(我认为)一个apply函数来优化我的循环,尽管我还没有弄清楚。

我已经尝试了一个嵌套的sapply,但是它似乎只能用于满足if语句的第一行。

settlements <- matrix(data = NA, nrow = 40, ncol = 5)
settlements[-seq(3, 40, 3), ] <- 0
for(i in seq(3, 40, 3)){
  for(j in 1:ncol(settlements)){
    if(j > i){
      settlements[i, j] <- 0
    }else{
      settlements[i, j] <- max(min(sum(expected_claims_pricing_cumulative[c(1:i), j]), sum(actual_claims[c(1:i), j])) - sum(expected_claims_discounted_cumulative[c(1:i), j]) - sum(settlements[c(1:(i - 1)), j]), 0)
    }
  }
}

因此上面的代码块可以工作,但是效率很低。

这是代码的示例输出:

           [,1]    [,2]      [,3]      [,4]     [,5]
 [1,]      0.0       0       0.0       0.0        0
 [2,]      0.0       0       0.0       0.0        0
 [3,] 121571.9       0  297009.7       0.0        0
 [4,]      0.0       0       0.0       0.0        0
 [5,]      0.0       0       0.0       0.0        0
 [6,] 217259.3       0  881364.8 1543090.3  1821937
 [7,]      0.0       0       0.0       0.0        0
 [8,]      0.0       0       0.0       0.0        0
 [9,] 219615.8       0 1398676.8 2050454.9  2788436
[10,]      0.0       0       0.0       0.0        0
[11,]      0.0       0       0.0       0.0        0
[12,] 577947.7       0 2007643.5 2995483.9  4163100
[13,]      0.0       0       0.0       0.0        0
[14,]      0.0       0       0.0       0.0        0
[15,] 641731.9 1184557 2148414.1 4253819.1  5908208
[16,]      0.0       0       0.0       0.0        0
[17,]      0.0       0       0.0       0.0        0
[18,] 862253.0       0       0.0 5727515.7  8081478
[19,]      0.0       0       0.0       0.0        0
[20,]      0.0       0       0.0       0.0        0
[21,] 796571.5       0 1588740.9 7260817.4 10380325
[22,]      0.0       0       0.0       0.0        0
[23,]      0.0       0       0.0       0.0        0
[24,] 302051.9       0       0.0 4496129.9        0
[25,]      0.0       0       0.0       0.0        0
[26,]      0.0       0       0.0       0.0        0
[27,] 112847.7       0       0.0 2148951.8        0
[28,]      0.0       0       0.0       0.0        0
[29,]      0.0       0       0.0       0.0        0
[30,]      0.0       0       0.0  338543.2        0
[31,]      0.0       0       0.0       0.0        0
[32,]      0.0       0       0.0       0.0        0
[33,]      0.0       0       0.0       0.0        0
[34,]      0.0       0       0.0       0.0        0
[35,]      0.0       0       0.0       0.0        0
[36,]      0.0       0       0.0       0.0        0
[37,]      0.0       0       0.0       0.0        0
[38,]      0.0       0       0.0       0.0        0
[39,]      0.0       0       0.0       0.0        0
[40,]      0.0       0       0.0       0.0        0

预计索赔价格累计:

1   246504.7    246504.7    246504.7    246504.7    246504.7
2   359684.6    729441.6    729441.6    729441.6    729441.6
3   450958.0    990484.9   1606746.6   1606746.6   1606746.6
4   536705.6   1213142.7   2112354.2   2851868.2   2851868.2
5   616642.8   1421701.3   2549096.4   3628150.1   4614168.9
6   735863.2   1660827.4   3002591.5   4355465.6   5794203.9
7   844157.6   1947952.3   3489559.4   5099676.3   6903508.4
8   958274.5   2224510.9   4064168.9   5914097.3   8060919.8
9  1060873.2   2498285.0   4608679.0   6816268.5   9282839.9
10 1177249.5   2768559.4   5164245.7   7696718.5  10640171.2
11 1358375.2   3124249.5   5776432.6   8651256.2  12027886.6
12 1536404.6   3573967.4   6517091.2   9699710.9  13532809.1
13 1712181.1   4016788.0   7412726.0  10944474.6  15187967.5
14 1868723.0   4436994.7   8278006.1  12353131.8  17062129.9
15 1999373.6   4802458.2   9082910.9  13692124.6  19125625.6
16 2289300.0   5288360.4   9960168.0  15096711.3  21242329.6
17 2492864.7   5926814.7  10925248.8  16531417.9  23380142.2
18 2715687.3   6454984.3  12178234.4  18176355.2  25651247.4
19 2955382.3   7028913.2  13261074.9  20128975.0  28126469.5
20 3200558.6   7633632.0  14422850.2  21901444.3  31058644.4
21  770767.5   5571605.4  12960061.0  21107123.0  31078581.7
22  823184.7   1979336.0   9980732.5  18846879.2  29709628.5
23  875275.7   2110052.8   4036971.6  13638647.3  25460176.4
24  928077.7   2240991.2   4298953.1   6611255.6  19413489.9
25  981284.6   2373401.1   4561590.4   7031144.6  10114214.6
26       0.0   1471926.9   3792121.1   6417948.2   9710687.1
27       0.0         0.0   2453211.5   5237444.5   8738547.3
28       0.0         0.0         0.0   2943853.8   6656164.5
29       0.0         0.0         0.0         0.0   3925138.4
30       0.0         0.0         0.0         0.0         0.0
31       0.0         0.0         0.0         0.0         0.0
32       0.0         0.0         0.0         0.0         0.0
33       0.0         0.0         0.0         0.0         0.0
34       0.0         0.0         0.0         0.0         0.0
35       0.0         0.0         0.0         0.0         0.0
36       0.0         0.0         0.0         0.0         0.0
37       0.0         0.0         0.0         0.0         0.0
38       0.0         0.0         0.0         0.0         0.0
39       0.0         0.0         0.0         0.0         0.0
40       0.0         0.0         0.0         0.0         0.0

预期的索赔已累计折现:

1   218156.6    218156.6    218156.6    218156.6    218156.6
2   318320.9    645555.8    645555.8    645555.8    645555.8
3   399097.9    876579.2   1421970.8   1421970.8   1421970.8
4   474984.5   1073631.3   1869433.4   2523903.4   2523903.4
5   545728.9   1258205.6   2255950.3   3210912.9   4083539.5
6   651238.9   1469832.3   2657293.5   3854587.0   5127870.5
7   747079.5   1723937.8   3088260.1   4513213.5   6109605.0
8   848073.0   1968692.2   3596789.4   5233976.2   7133914.1
9   938872.8   2210982.3   4078680.9   6032397.7   8215313.3
10 1041865.8   2450175.0   4570357.5   6811595.9   9416551.5
11 1202162.1   2764960.8   5112142.9   7656361.8  10644679.6
12 1359718.1   3162961.2   5767625.8   8584244.2  11976536.1
13 1515280.3   3554857.3   6560262.6   9685860.0  13441351.3
14 1653819.9   3926740.3   7326035.4  10932521.7  15099985.0
15 1769445.7   4250175.5   8038376.2  12117530.3  16926178.6
16 2026030.5   4680199.0   8814748.7  13360589.5  18799461.7
17 2206185.2   5245231.0   9668845.1  14630304.8  20691425.9
18 2403383.3   5712661.1  10777737.4  16086074.4  22701353.9
19 2615513.3   6220588.2  11736051.3  17814142.9  24891925.5
20 2832494.4   6755764.3  12764222.5  19382778.2  27486900.3
21  682129.2   4930870.8  11469654.0  18679803.8  27504544.8
22  728518.5   1751712.4   8832948.2  16679488.1  26293021.2
23  774619.0   1867396.7   3572719.8  12070202.9  22532256.1
24  821348.7   1983277.2   3804573.5   5850961.2  17180938.6
25  868436.9   2100460.0   4037007.5   6222562.9   8951079.9
26       0.0   1302655.3   3356027.1   5679884.1   8593958.1
27       0.0         0.0   2171092.2   4635138.4   7733614.4
28       0.0         0.0         0.0   2605310.6   5890705.5
29       0.0         0.0         0.0         0.0   3473747.5
30       0.0         0.0         0.0         0.0         0.0
31       0.0         0.0         0.0         0.0         0.0
32       0.0         0.0         0.0         0.0         0.0
33       0.0         0.0         0.0         0.0         0.0
34       0.0         0.0         0.0         0.0         0.0
35       0.0         0.0         0.0         0.0         0.0
36       0.0         0.0         0.0         0.0         0.0
37       0.0         0.0         0.0         0.0         0.0
38       0.0         0.0         0.0         0.0         0.0
39       0.0         0.0         0.0         0.0         0.0
40       0.0         0.0         0.0         0.0         0.0

实际声明:

         [,1]    [,2]     [,3]     [,4]     [,5]
 [1,]       0       0        0    60000   610000
 [2,]       0  420000   530000   960000   410000
 [3,] 1110000  660000  4140000  2260000   810000
 [4,]  330000  750000  3550000  3480000  1070000
 [5,] 1790000  850000  2140000  5090000  6120000
 [6,] 2110000  540000  3940000  7440000  9500000
 [7,]       0 1260000  2170000  7010000  9110000
 [8,]  120000 3520000  5280000  6260000 10900000
 [9,]  240000  210000  2610000  5730000  9140000
[10,] 2130000 2070000  5840000 14570000  6600000
[11,] 1430000 5110000  5810000 13540000 18910000
[12,]  860000 1140000  3970000 11630000 14430000
[13,] 2410000 5890000  8360000 13220000 15890000
[14,] 1550000  950000  9820000 12150000 21450000
[15,] 1960000 9370000  5780000  7740000 18530000
[16,] 4160000 5430000  4590000 14150000 17190000
[17,] 3930000 3450000  8190000 16840000 20080000
[18,]  590000 5290000 11690000 17580000 25380000
[19,] 2760000 4470000 19390000 20990000 28200000
[20,] 3450000 7140000  9740000 21740000 21070000
[21,]  820000 3780000 13220000 24690000 33260000
[22,]       0 2410000  4380000 19070000 30780000
[23,] 1930000  360000  2030000  9470000 15680000
[24,] 2460000 3620000  3140000  1540000 12560000
[25,]       0 4170000  6600000  5970000  8770000
[26,]       0 1280000  6890000  4940000  4530000
[27,]       0       0   740000  2880000  8280000
[28,]       0       0        0  4020000  9550000
[29,]       0       0        0        0  4960000
[30,]       0       0        0        0        0
[31,]       0       0        0        0        0
[32,]       0       0        0        0        0
[33,]       0       0        0        0        0
[34,]       0       0        0        0        0
[35,]       0       0        0        0        0
[36,]       0       0        0        0        0
[37,]       0       0        0        0        0
[38,]       0       0        0        0        0
[39,]       0       0        0        0        0
[40,]       0       0        0        0        0

2 个答案:

答案 0 :(得分:3)

您可以使用outer来获取元素,并使用[<-replace来放入元素。

settlements <- matrix(data = 0, nrow = 40, ncol = 5)

myfun <- function(i, j){
  3*i/sqrt(j) 
}

settlements[seq(3, nrow(settlements), 3),] <- 
  outer(seq(3, nrow(settlements), 3), seq(ncol(settlements)), myfun)

# or 
# settlements[seq(3, nrow(settlements), 3),] <- 
#   do.call(myfun,
#           expand.grid(i = seq(3, nrow(settlements), 3), 
#                       j = seq(ncol(settlements))))

# or replace(settlements, row(settlements) %% 3 == 0, outer_output)
# if you want to create a new matrix

settlements

#       [,1]      [,2]      [,3] [,4]      [,5]
#  [1,]    0  0.000000  0.000000  0.0  0.000000
#  [2,]    0  0.000000  0.000000  0.0  0.000000
#  [3,]    9  6.363961  5.196152  4.5  4.024922
#  [4,]    0  0.000000  0.000000  0.0  0.000000
#  [5,]    0  0.000000  0.000000  0.0  0.000000
#  [6,]   18 12.727922 10.392305  9.0  8.049845
#  [7,]    0  0.000000  0.000000  0.0  0.000000
#  [8,]    0  0.000000  0.000000  0.0  0.000000
#  [9,]   27 19.091883 15.588457 13.5 12.074767
# [10,]    0  0.000000  0.000000  0.0  0.000000
# [11,]    0  0.000000  0.000000  0.0  0.000000
# [12,]   36 25.455844 20.784610 18.0 16.099689
# [13,]    0  0.000000  0.000000  0.0  0.000000
# [14,]    0  0.000000  0.000000  0.0  0.000000
# [15,]   45 31.819805 25.980762 22.5 20.124612
# [16,]    0  0.000000  0.000000  0.0  0.000000
# [17,]    0  0.000000  0.000000  0.0  0.000000
# [18,]   54 38.183766 31.176915 27.0 24.149534
# [19,]    0  0.000000  0.000000  0.0  0.000000
# [20,]    0  0.000000  0.000000  0.0  0.000000
# [21,]   63 44.547727 36.373067 31.5 28.174457
# [22,]    0  0.000000  0.000000  0.0  0.000000
# [23,]    0  0.000000  0.000000  0.0  0.000000
# [24,]   72 50.911688 41.569219 36.0 32.199379
# [25,]    0  0.000000  0.000000  0.0  0.000000
# [26,]    0  0.000000  0.000000  0.0  0.000000
# [27,]   81 57.275649 46.765372 40.5 36.224301
# [28,]    0  0.000000  0.000000  0.0  0.000000
# [29,]    0  0.000000  0.000000  0.0  0.000000
# [30,]   90 63.639610 51.961524 45.0 40.249224
# [31,]    0  0.000000  0.000000  0.0  0.000000
# [32,]    0  0.000000  0.000000  0.0  0.000000
# [33,]   99 70.003571 57.157677 49.5 44.274146
# [34,]    0  0.000000  0.000000  0.0  0.000000
# [35,]    0  0.000000  0.000000  0.0  0.000000
# [36,]  108 76.367532 62.353829 54.0 48.299068
# [37,]    0  0.000000  0.000000  0.0  0.000000
# [38,]    0  0.000000  0.000000  0.0  0.000000
# [39,]  117 82.731493 67.549981 58.5 52.323991
# [40,]    0  0.000000  0.000000  0.0  0.000000

您始终可以直接根据row()col()编写操作来创建新矩阵

row(settlements)/3 + col(settlements)^2.5

#            [,1]      [,2]     [,3]     [,4]     [,5]
#  [1,]  1.333333  5.990188 15.92179 32.33333 56.23503
#  [2,]  1.666667  6.323521 16.25512 32.66667 56.56837
#  [3,]  2.000000  6.656854 16.58846 33.00000 56.90170
#  [4,]  2.333333  6.990188 16.92179 33.33333 57.23503
#  [5,]  2.666667  7.323521 17.25512 33.66667 57.56837
#  [6,]  3.000000  7.656854 17.58846 34.00000 57.90170
#  [7,]  3.333333  7.990188 17.92179 34.33333 58.23503
#  [8,]  3.666667  8.323521 18.25512 34.66667 58.56837
#  [9,]  4.000000  8.656854 18.58846 35.00000 58.90170
# [10,]  4.333333  8.990188 18.92179 35.33333 59.23503
# [11,]  4.666667  9.323521 19.25512 35.66667 59.56837
# [12,]  5.000000  9.656854 19.58846 36.00000 59.90170
# [13,]  5.333333  9.990188 19.92179 36.33333 60.23503
# [14,]  5.666667 10.323521 20.25512 36.66667 60.56837
# [15,]  6.000000 10.656854 20.58846 37.00000 60.90170
# [16,]  6.333333 10.990188 20.92179 37.33333 61.23503
# [17,]  6.666667 11.323521 21.25512 37.66667 61.56837
# [18,]  7.000000 11.656854 21.58846 38.00000 61.90170
# [19,]  7.333333 11.990188 21.92179 38.33333 62.23503
# [20,]  7.666667 12.323521 22.25512 38.66667 62.56837
# [21,]  8.000000 12.656854 22.58846 39.00000 62.90170
# [22,]  8.333333 12.990188 22.92179 39.33333 63.23503
# [23,]  8.666667 13.323521 23.25512 39.66667 63.56837
# [24,]  9.000000 13.656854 23.58846 40.00000 63.90170
# [25,]  9.333333 13.990188 23.92179 40.33333 64.23503
# [26,]  9.666667 14.323521 24.25512 40.66667 64.56837
# [27,] 10.000000 14.656854 24.58846 41.00000 64.90170
# [28,] 10.333333 14.990188 24.92179 41.33333 65.23503
# [29,] 10.666667 15.323521 25.25512 41.66667 65.56837
# [30,] 11.000000 15.656854 25.58846 42.00000 65.90170
# [31,] 11.333333 15.990188 25.92179 42.33333 66.23503
# [32,] 11.666667 16.323521 26.25512 42.66667 66.56837
# [33,] 12.000000 16.656854 26.58846 43.00000 66.90170
# [34,] 12.333333 16.990188 26.92179 43.33333 67.23503
# [35,] 12.666667 17.323521 27.25512 43.66667 67.56837
# [36,] 13.000000 17.656854 27.58846 44.00000 67.90170
# [37,] 13.333333 17.990188 27.92179 44.33333 68.23503
# [38,] 13.666667 18.323521 28.25512 44.66667 68.56837
# [39,] 14.000000 18.656854 28.58846 45.00000 68.90170
# [40,] 14.333333 18.990188 28.92179 45.33333 69.23503

使用ifelse

的更复杂的示例
new <- 
  ifelse(sqrt(row(settlements)*col(settlements)) > 5, 
         row(settlements)*col(settlements)^1.2, 
         row(settlements) + 44)
dim(new) <- dim(settlements)
new
#       [,1]     [,2]      [,3]      [,4]      [,5]
#  [1,]   45 45.00000  45.00000  45.00000  45.00000
#  [2,]   46 46.00000  46.00000  46.00000  46.00000
#  [3,]   47 47.00000  47.00000  47.00000  47.00000
#  [4,]   48 48.00000  48.00000  48.00000  48.00000
#  [5,]   49 49.00000  49.00000  49.00000  49.00000
#  [6,]   50 50.00000  50.00000  50.00000  41.39189
#  [7,]   51 51.00000  51.00000  36.94622  48.29054
#  [8,]   52 52.00000  52.00000  42.22425  55.18919
#  [9,]   53 53.00000  33.63474  47.50228  62.08783
# [10,]   54 54.00000  37.37193  52.78032  68.98648
# [11,]   55 55.00000  41.10912  58.05835  75.88513
# [12,]   56 56.00000  44.84631  63.33638  82.78378
# [13,]   57 29.86616  48.58351  68.61441  89.68243
# [14,]   58 32.16355  52.32070  73.89244  96.58108
# [15,]   59 34.46095  56.05789  79.17047 103.47972
# [16,]   60 36.75835  59.79509  84.44851 110.37837
# [17,]   61 39.05574  63.53228  89.72654 117.27702
# [18,]   62 41.35314  67.26947  95.00457 124.17567
# [19,]   63 43.65054  71.00666 100.28260 131.07432
# [20,]   64 45.94793  74.74386 105.56063 137.97297
# [21,]   65 48.24533  78.48105 110.83866 144.87161
# [22,]   66 50.54273  82.21824 116.11670 151.77026
# [23,]   67 52.84012  85.95543 121.39473 158.66891
# [24,]   68 55.13752  89.69263 126.67276 165.56756
# [25,]   69 57.43492  93.42982 131.95079 172.46621
# [26,]   26 59.73231  97.16701 137.22882 179.36486
# [27,]   27 62.02971 100.90421 142.50685 186.26350
# [28,]   28 64.32711 104.64140 147.78489 193.16215
# [29,]   29 66.62450 108.37859 153.06292 200.06080
# [30,]   30 68.92190 112.11578 158.34095 206.95945
# [31,]   31 71.21930 115.85298 163.61898 213.85810
# [32,]   32 73.51669 119.59017 168.89701 220.75675
# [33,]   33 75.81409 123.32736 174.17504 227.65539
# [34,]   34 78.11149 127.06456 179.45308 234.55404
# [35,]   35 80.40888 130.80175 184.73111 241.45269
# [36,]   36 82.70628 134.53894 190.00914 248.35134
# [37,]   37 85.00368 138.27613 195.28717 255.24999
# [38,]   38 87.30107 142.01333 200.56520 262.14864
# [39,]   39 89.59847 145.75052 205.84323 269.04728
# [40,]   40 91.89587 149.48771 211.12127 275.94593

答案 1 :(得分:0)

编辑

基于上述@IceCreamToucan的答案---我不知道rowcol!---您也可以按照以下步骤做很多事情:

map2(row(settlements), col(settlements), FUN) %>%
    matrix(nrow = 40, ncol = 5)

原始答案

不幸的是,如果您想在R中进行功能上的操作,将事物视为向量而不是矩阵要容易得多。幸运的是,矩阵实际上是 向量。困难的部分是找回ij索引。

由于语法要简单一些,因此我将使用purrr。这有点混乱---如果您希望此代码可重现,我将清理map_int的参数---但基本的想法是执行以下操作:

library(functional)
library(purrr)

#  Make a function that can convert back and forth between position in vector
#+ and the indices of the same element in the matrix. 
get_indices <- function(nrow, n) {
  i <- ((n - 1) %% nrow) + 1
  j <- ((n - 1) %/% nrow) + 1
  list(i = i, j = j)
}

#  Initialize your matrix, but fill it with the position of each element of the
#+ vector.
settlements <- matrix(1:200, nrow = 40, ncol = 5)

#  Apply your function, and then turn it back into a matrix
map_dbl(settlements, ~do.call("FUN", Curry(get_indices, nrow = 40)(.))) %>%
  matrix(nrow = 40, ncol = 5)