0

I have an xts object dollarReturn. I am trying to sum all the values of the column CL where the previous day's return was below a certain threshold X.

I am getting the error:

Error in +.default (sum, value) : non-numeric argument to binary operator

My loops:

for(n in 1:nrow(dollarReturn)){
  X = -2000
  value = ifelse(dollarReturn$CL[n] < X,dollarReturn$CL[n+1],0)
  sum = sum + value
  print(n)
  return(sum)
}

datasample:

structure(c(-2439.99999999999, -880.000000000002, 779.999999999992, 
590.000000000018, -70.0000000000061, -189.999999999997), .indexCLASS = "Date", .indexTZ = "UTC", tclass = "Date", tzone = "UTC", class = c("xts", 
"zoo"), index = structure(c(1420416000, 1420502400, 1420588800, 
1420675200, 1420761600, 1421020800), tzone = "UTC", tclass = "Date"), .Dim = c(6L, 
1L), .Dimnames = list(NULL, "CL"))

2015-01-05 -2440
2015-01-06  -880
2015-01-07   780
2015-01-08   590
2015-01-09   -70
2015-01-12  -190
  • Add `print(n)` to your loop and you should realize what the issue is. Also, you don't need a loop for this. – Roland Dec 14 '17 at 07:03
  • Roland I updated the for loop. If I knew how to do this without a loop I would do it. At least give a suggestion on how it might be done without a loop. – RulesOfTheGame Dec 14 '17 at 07:14
  • I'm sorry, but how do you expect me to write and test code without a [reproducible data sample](https://stackoverflow.com/a/5963610/1412059)? Your updated code doesn't appear to be related to the error message anymore. – Roland Dec 14 '17 at 07:18
  • You should be able to use a combination of subsetting and the `cumsum` function. – Roland Dec 14 '17 at 07:20
  • I added a datasample and the loop still gives me the same error. I will look into subsetting and cumsum, but I would like to understand how to do it this way. – RulesOfTheGame Dec 14 '17 at 07:33
  • It appears you didn't follow the link I helpfully supplied in my comment. – Roland Dec 14 '17 at 07:35
  • I didn't see your link. I have updated the data sample as requested. – RulesOfTheGame Dec 14 '17 at 07:45
  • Is the expected result what `sum(dollarReturn$CL[c(FALSE, head(dollarReturn$CL < -2000, -1))])` returns? I'm not sure because your first loop was totally different than what you show now. – Roland Dec 14 '17 at 07:55

1 Answers1

2

You cannot use standard function sum as a variable.

Try this:

summ = 0
for(n in 1:nrow(dollarReturn)){
  X = -2000
  value = ifelse(dollarReturn$CL[n] < X,dollarReturn$CL[n+1],0)
  summ = summ + value
  print(n)
}
print(summ).

Also, it's better to use ifelse(dollarReturn$CL[[n]] < X,dollarReturn$CL[[n+1]],0) instead of ifelse(dollarReturn$CL[n] < X,dollarReturn$CL[n+1],0)

So, you strongly should to vectorize your operations. The code below is an attempt to improve your current code.

boolArr <- as.numeric(dollarReturn$CL < X);
summ2 <- sum(dollarReturn$CL[2:nrow(dollarReturn)] * boolArr[1:(nrow(dollarReturn)-1)]);
print(summ2)

But my own experience, using data.table instead of xts improve code execution dramatically. I don't know why, but it's a fact.

Dmitriy
  • 847
  • 17
  • 39
  • 1
    I cannot get the for loop to work but your improvement code works. Thank you. – RulesOfTheGame Dec 14 '17 at 08:27
  • Nope. Glad to help! – Dmitriy Dec 14 '17 at 08:28
  • You do not want to use `ifelse` like that in a loop. `ifelse` is vectorized, in a loop you should use `if` and `else`. – Roland Dec 14 '17 at 09:10
  • if statement is also vectorized.))) Ifelse is just an R wrapper, you could see code of it by 'ifelse' command in R console. You could use both 'if' or 'ifelse' for single numerics. But, of course, it's better to use vectorized approach in code. – Dmitriy Dec 14 '17 at 09:14