Reputation: 45
I am trying to move a functional function from excel (vba) to R and I seem to be having some issues, I believe that my main problem is with the "while loop" that works differently in R.
I have a matrix of vectors that have a mix of 0s and values. I am trying to extract the maximum values of the sections between two 0s. Here is a sample vector:
0
1.635575602
11.93874271
15.20341137
18.16580908
23.08093719
23.08093719
28.63988978
29.47908862
31.27956405
34.62045861
35.86468375
35.67169884
34.41910372
34.13588804
36.35702777
30.61167441
29.83991346
31.5377766
33.36361359
38.39661051
41.7296732
41.25382922
42.201721
41.60610325
39.2679181
42.41767147
44.35414715
47.01404223
47.78679762
48.19090854
46.00970043
47.43423273
49.3390832
52.82529397
52.64059228
54.67565536
55.88442219
52.68092051
51.72507703
49.48208145
50.73345177
51.33687453
53.54355564
54.81330186
55.55989561
56.79134235
56.53052551
57.29075015
58.29989275
58.92019776
58.49267229
57.35840588
56.44372409
57.12120899
58.65510461
54.96689316
53.85952168
49.10602435
48.34147823
48.21719951
50.2662308
52.05459443
50.36193646
49.49321984
48.16627652
37.72978919
18.89787599
10.83759454
14.209174
7.93
0
0
0
0
0
0
0
2.24
0
0
2.61
0
0
3.994244
7.74
0
0
1.39
0
0.833740358
5.591908185
3.724156828
11.52743689
8.583836427
10.40266238
11.10493341
16.34192867
15.36866836
15.22455009
14.729984
10.88
0
4.655296
2.63
0
0
4.344807644
5.721277
6.83
0
0
0
0
0
0
0
0
2.438044526
2.584168274
5.366396225
7.836381209
6.26157568
0.7744
2.72
0
3.103570031
2.938565593
3.10329
4.91
0
0
0
From this vector I am trying to obtain MaxLoss = 58.92, 2.24, 2.61, 7.74, 1.39, 16.34, 4.65, 6.83, 7.84 and 4.91 which are the maximum values between each 0s.
Here is the code I've tried, almost identical (in form) to the VBA equivalent that works:
MaxLoss <- matrix(data=0,ncol=LengthNames,nrow=LengthDates)
for (j in 1:LengthNames){
k <- 0
for (i in 1:LengthDates){
if (is.na(Drawd2[i,j]) == TRUE){
break
} else if (Drawd2[i,j] != 0){
k <- k+1
PeakStart[k,j] <- as.Date(Dates[i])
while (Drawd2[i,j] != 0){
# k <- k
#if (is.na(Drawd[i,j]) == TRUE){
# break
#}
if (Drawd2[i,j] > MaxLoss[k,j]){
MaxLoss[k,j] <- Drawd2[i,j]
}
if (i == LengthDates){
break
}
i <- i+1
} # end while
i <- i-1
} # end elseif
} # end for i
} # end for j
Drawd2 is the vector I pasted, LengthNames is the number of columns and LengthNames is the length of the vector
It seems as though k keeps adding within the while loop, rather than adding 1 only once per while sequence. Instead of having 10 values, I get 103 values. I tried to force it to stay at k within each while but to no avail. As such, the code works, but it gives me more than the desired values.
If I export the vector into .csv it seems to leave the 0s as blank but R reads them as 0s:
> Drawd2[1,1]!=0
[1] FALSE
> Drawd2[2,1]!=0
[1] TRUE
I assume what I did is not optimal, but while my first step was to transcribe my code in R, I welcome any kind of optimization and help. Also, if I were to remove the first for loop (j), it still does not work but I wanted to show the end goal.
Upvotes: 1
Views: 447
Reputation: 59980
I'm assuming your vector is called x
. Split it into segments, delimited by the zeros in your dataset. Then find the max in each segment and finally remove those segments for which were composed entirely of zeroes (because you have repetitive zeroes in the vector).
3 simple lines!
y <- split( x , cumsum(x==0) )
res <- sapply( y , max )
res[ res != 0 ]
# 1 8 10 12 14 15 16 18 26
#58.920198 2.240000 2.610000 7.740000 1.390000 16.341929 4.655296 6.830000 7.836381
# 27
# 4.910000
If you need to apply this to each column or row in a matrix look at apply
.
Upvotes: 2