Reputation: 113
This is an extension of the question
How to isolate the output of a reactive (function) and save to a data.frame?
Basically I want to construct a table based on a vector with predetermined and added values. I want to show as tableoutput the original vector and a column with the roll mean of the previous 4 values of this vector. For instance, if the user added the value 200, I will have
d <- c(rep(100,4),200)
and using zoo::rollapply() I have the roll mean of the previous 4 values of d
md <- rollapply(d , mean , fill = NA, width = list(-1:-4))
the expected result
cbind(d,md)
d md
[1,] 100 NA
[2,] 100 NA
[3,] 100 NA
[4,] 100 NA
[5,] 200 100
In my shiny app I am not able to use my function, the app close when I add a value. But if I use other function like input$c1 + 5 it works. I think that the problem is that I do not know how to capture the updated vector and use it to run a function that needs a vector as input. Furthermore, to run the app I needed to match the same number of rows in the new column.
Here is my UI code:
library(shiny)
fluidPage(
sidebarPanel(textInput("c1","example"),
actionButton("update", "Update Table")
),
mainPanel(tableOutput("example")
)
)
and the server
library(shiny)
library(zoo)
function(input, output) {
#Example
d <- c(rep(100,4))
m <- c(rep(100,4))
md <- reactive(
rollapply(values$df , mean , fill=NA , width=list(-1:-4))
)
values <- reactiveValues(df = data.frame('D' = d, 'M_D'= m))
newEntry <- observe({
if(input$update > 0) {
values$df <- isolate(rbind(values$df,data.frame('D' =input$c1,
'M_D' = md())))
}
})
output$example <- renderTable({values$df})
}
Upvotes: 3
Views: 4319
Reputation: 22827
So I would say were using too many different shiny mechanisms and they were tripping over each other. I made the following changes:
observe
to observeEvent
so as to confine the calculations to when you pres the update
button.isolate
usage as it is not needed in an observeEvent
as opposed to an observe
.md()
function as you already have that data stored in a reactiveValues
list.rollingapply
operate only on the relevant columns instead of the entire data frame.c()
in c(rep(...))
, etc.as.numeric
to the input$c1
processing otherwise it was causing that column to convert to a factor and change its values.So here is the code:
library(shiny)
library(zoo)
u <- fluidPage(
sidebarPanel(textInput("c1","example"),
actionButton("update", "Update Table")
),
mainPanel(tableOutput("example")
)
)
s <- function(input, output) {
#Example
d <- rep(100,4)
m <- rep(100,4)
values <- reactiveValues(df = data.frame(D=d, M_D=m))
newEntry <- observeEvent(input$update,{
d_new <- c(values$df$D,as.numeric(input$c1))
m_d_new <- rollapply(d_new, mean , fill=NA , width=list(-1:-4))
values$df <- data.frame(D=d_new,M_D=m_d_new)
})
output$example <- renderTable({values$df})
}
shinyApp(u,s)
Which yields the following after entering 200
and pressing Update Table
a few times:
Upvotes: 4