iamsoconfused12321
iamsoconfused12321

Reputation: 33

What apply should I use to optimize this nested for loop with an if statement?

I'm running 100,000 simulations using R, and this code chunk is part of the simulation process. I understand that R is not very kind with for loops, so I would like to optimize my loop with (I think) an apply function, though I haven't figured that out yet.

I've tried a nested sapply, but it only seemed to work with the first row that fulfilled the if statement.

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

So the code chunk above works, but clearly inefficient.

This is a sample output of the code:

           [,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

expected claims pricing cumulative:

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

expected claims discounted cumulative:

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

actual claims:

         [,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

Upvotes: 2

Views: 49

Answers (2)

jgaeb
jgaeb

Reputation: 317

edit

Based on the answer from @IceCreamToucan above---I didn't know about row and col!---you could also do this much simply as follows:

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

original answer

Unfortunately, if you want to do something functionally in R, it's much easier to think of things as vectors, rather than as matrices. Fortunately, matrices really are vectors under the hood; the hard part is getting back the i and j indices.

I'm going to use purrr since the syntax is a little easier. This is a bit messy---if you want this to be reproducible, I would clean up the arguments to map_int---but the basic idea is to do something like this:

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)

Upvotes: 0

IceCreamToucan
IceCreamToucan

Reputation: 28685

You can use outer to get the elements and either [<- or replace to put them in.

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

You can always just write an operation directly in terms of row() and col() to create a new matrix

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

A more complex example using 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

Upvotes: 3

Related Questions