Hello all!
I am new to shiny, and although I have managed to get my code working, there is something that I just cannot get my head around. Below is a code that solves a system of two differential equations, with coefficients being selected using Shiny sliders, and in the main panel I am trying to select which of the two variables to plot. The problem is that since selection of the plotting variable is part of the "input", if I change a variable that I want to plot, this results in the recalculation of the whole thing. I have attached a short code illustrating this problem on the example of a small system, but in reality I have a really large system of ODEs that takes quite a lot of time to solve, so I really need to make sure that if the sliders with parameters are not changed, the system is only solved once, and I can then separately plot each of the variables without a time-consuming recalculation of the whole thing.
I have had a look at "reactive" as an option, but can't see how to make it work for this. I have tried to make it reactive by writing sim=reactive({Run_LV(input)})
but it returns an error message "Error in $: object of type 'closure' is not subsettable" Any idea what I could be doing wrong? I've also tried sim=reactive({as.data.frame(Run_LV(input))})
but get the same error.
Could you please have a look at the short code below and let me know if that's possible, and more specifically, how to make it plot either U or V but without solving the system again.
Thanks a lot in advance!
library(deSolve)
library(shiny)
library(shinyWidgets)
library(plotly)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
column(width=6,
sliderInput("a", "Coef 1",0, 5, 1, step=0.2),
sliderInput("b", "Coef 2", 0, 5, 1, step=0.2)
)
)
),
mainPanel(
selectInput("Var",
label = "Choose variable to plot:",
choices = c("First"="U", "Second"="V"),
selected = c("U")
),
plotlyOutput("plot0")
)
)
)
LV=function(t,y,p){ # define Lotka-Volterra system
with(as.list(p),{
z=rep(0,2)
z[1]=y[1]-a*y[1]*y[2]
z[2]=b*y[1]*y[2]-y[2]
return(list(z))
})
}
Run_LV=function(p){ # run the simmulation
t = seq(from=0, to=10, by=0.1)
y0=c(1.5,0.7) # initial condition
para=c(list("a"=p$a,"b"=p$b)) # values of parameters
out = ode(y=y0, times=t, func=LV, parms=para ,method="ode45")
return(list("out"=out))
}
server <- function(input, output) {
output$plot0=renderPlot({
sim=Run_LV(input)
sol=sim$out
xvar=sol[,1] # time
if(input$Var=="U"){
yvar=sol[,2] # will plot U component
}else{
yvar=sol[,3] # will plot V component
}
data<- data.frame(xvar,yvar)
p=plot_ly(data,x=~xvar, y=~yvar, type = 'scatter', mode = 'lines')
p
})
}
shinyApp(ui = ui, server = server)