Reputation: 419
I met a problem with for loop in Shiny server and no one can find out how to fix it till now. I have been working on this for days but still didn't get any progress. Long story short, please just look at the following code. I was trying to fetch data from Google Finance and calculated the smoothed variance.
stock2 <-
reactive(
getSymbols(
toupper(input$ticker2),
from = as.Date(input$date2[1]) - 150,
to = input$date2[2],
src = "google",
auto.assign = F
)
)
stock3 <- reactive(as.data.table(stock2()))
stock <- reactive(as.data.frame(stock3()))
stock.return <- reactive(diff(log(stock()[, 5])))
stock.mu <- reactive(mean(stock.return()))
stock.var <- reactive((stock.return() - stock.mu()) ^ 2)
stock.var.smoothed <- reactive(rep(0, length(stock.return())))
Code above works totally fine and I have tested that.
So the problem is the following code, I want to assign a vector based on some calculation but I don't know the proper way to do it.
stock.var.smoothed <- reactive({
for (i in 2:length(stock.var())) {
stock.var.smoothed[1] <<- stock.var()[1]
stock.var.smoothed[i] <<-
(1 - input$alpha) * stock.var.smoothed()[i - 1] + input$alpha * stock.var()[i]
}
})
The for loop doesn't work at all. The error code is
Error: object of type 'closure' is not subsettable
But I already used () for the variables inside the function. So I have no idea how to fix that.
BTW, I also tried the following code
for (i in 2:length(stock.return())) {
stock.momentum.smoothed[1] <- reactive(stock.momentum()[1])
stock.momentum.smoothed[i] <-
reactive((1 - input$beta) * stock.momentum.smoothed()[i - 1] + input$beta * stock.return()[i])
}
The error code is
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
I appreciate anyone that could give any help. Thank you!
Upvotes: 2
Views: 6016
Reputation: 546113
Your subset assignment to the reactive (stock.var.smoothed[1] <<-
) simply doesn’t make sense: this operation wouldn’t be what you want, even without the subsetting (it would replace your reactive object with a non-reactive value; i.e. it would stop being reactive).
You can create and assign to variables inside your reactive expression. But don’t assign to the global environment (i.e. don’t use <<-
), and don’t try to reassign the reactive object itself. Instead, create a local temporary variable:
stock.var.smoothed <- reactive({
value <- numeric(length(stock.var()))
value[1] <- stock.var()[1]
for (i in 2 : length(stock.var())) {
value[i] <- (1 - input$alpha) * value[i - 1] + input$alpha * stock.var()[i]
}
value
})
Here, value
could be any name (including stock.var.smoothed
— but this would be a different variable than your reactive, because it’s in a different scope).
Furthermore, I’m pretty sure that this code be written without a loop and temporary variable (but it’s not immediately obvious how it would look like to me).
Finally, a note on code style: don’t use .
inside variable names. This is confusing, since it’s also used for S3 dispatch to separate the method’s generic name and class name. A common convention in R is to use underscores instead (stock_var_smoothed
).
Upvotes: 9