AcceptableCarrot
AcceptableCarrot

Reputation: 71

Updating a data frame in real time in RShiny

I am trying to get my head around RShiny by building what I thought would be a pretty simple but useful app. What I would like the app to do is allow the user to input some data made up of dates, numeric, and characters. Then when the user presses a save/submit button this data is appended onto a pre-existing data frame made up of previous recordings and over write the .csv of these recordings. I would also like this data to be presented to the users in the form of a table in the UI which is updated as soon as the user presses the save/submit button.

I have managed to get the majority of the UI features working, however, I am having real difficulty 1) saving the data in the correct format and 2) updating the table displayed on the UI. My current method of saving the data involves creating an isolated list of the input values and rbinding this to the original data frame. However, the formats of the input values appear to all revert to factors which is especially problematic with the date as the output is meaningless as far as I am aware. In terms of updating the UI I have attempted to create a reactive object out of the data frame and use this object as the data displayed in renderDataTable but this approach seems to have no affect.

I have created a dummy minimal example below.

Thank you for all your help in advance.

require(shiny)
require(tidyverse)
require(lubridate)
require(plotly)

#Would import the data in reality using read.csv() but to allow for an easily
#recreated example I made a dummy data frame 
DateRecorded <- dmy(c("10/07/2018", "11/07/2018", "13/07/2018"))
Value <- c(1, 2, 3)
Person <- c("Bob", "Amy", "Charlotte")

df <- data.frame(DateRecorded, Value, Person)

ui <- fluidPage(
  #UI Inputs
  dateInput(inputId = "SessionDate", label = "Date Recorded", format = "dd-mm-yyyy"),

  numericInput(inputId = "SessionValue", label = "Value Recorded", value = 0),

  textInput(inputId = "SessionPerson", label = "Person Recording"),

  actionButton(inputId = "Save", label = "Save"),

  #UI Outputs
  dataTableOutput("TheData"),
  textOutput("TotRecorded")
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  #When "Save" is pressed should append data to df and export
  observeEvent(input$Save, {
    newLine <- isolate(c(input$SessionDate, input$SessionValue, input$SessionPerson))

    isolate(df <- rbind(as.matrix(df), unlist(newLine)))

    write.csv(df, "ExampleDataFrame.csv") #This export works but the date is saved incorrectly as "17729" not sure why
  })

  #Create a reactive dataset to allow for easy updating
  ReactiveDf <- reactive({
    df
  })

  #Create the table of all the data
  output$TheData <- renderDataTable({
    ReactiveDf()
  })

  #Create the totals print outs
  output$TotRecorded <- renderPrint({
    data <- ReactiveDf()
    cat(nrow(data))
  })

}

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 2

Views: 1173

Answers (1)

Florian
Florian

Reputation: 25395

I made some small tweaks.

  • You do not need isolate in the body of the observeEvent; it does not take a reactive dependency to values in its body.
  • I made ReactiveDf a reactiveVal instead of a reactive. This allows you to write its value from inside an observeEvent.
  • Instead of rowbinding a matrix and unlisting a list - the issue is that all the new values are parsed to the same class, while they are obviously not - it might be easier to rbind two data.frames, so create the newLine with newLine <- data.frame(DateRecorded = input$SessionDate, Value = input$SessionValue, Person = input$SessionPerson)

So a working example would be as shown below. Hope this helps!

require(shiny)
require(tidyverse)
require(lubridate)
require(plotly)

#Would import the data in reality using read.csv() but to allow for an easily
#recreated example I made a dummy data frame 
DateRecorded <- dmy(c("10/07/2018", "11/07/2018", "13/07/2018"))
Value <- c(1, 2, 3)
Person <- c("Bob", "Amy", "Charlotte")

df <- data.frame(DateRecorded, Value, Person)

ui <- fluidPage(
  #UI Inputs
  dateInput(inputId = "SessionDate", label = "Date Recorded", format = "dd-mm-yyyy"),
  numericInput(inputId = "SessionValue", label = "Value Recorded", value = 0),
  textInput(inputId = "SessionPerson", label = "Person Recording"),
  actionButton(inputId = "Save", label = "Save"),

  #UI Outputs
  dataTableOutput("TheData"),
  textOutput("TotRecorded")
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  #When "Save" is pressed should append data to df and export
  observeEvent(input$Save, {
    newLine <- data.frame(DateRecorded = input$SessionDate, Value = input$SessionValue, Person = input$SessionPerson)
    df <- rbind(df, newLine)
    ReactiveDf(df) # set reactiveVal's value.
    write.csv(df, "ExampleDataFrame.csv") #This export works but the date is saved incorrectly as "17729" not sure why
  })

  #Create a reactive dataset to allow for easy updating
  ReactiveDf <- reactiveVal(df)

  #Create the table of all the data
  output$TheData <- renderDataTable({
    ReactiveDf()
  })

  #Create the totals print outs
  output$TotRecorded <- renderPrint({
    data <- ReactiveDf()
    cat(nrow(data))
  })

}

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 2

Related Questions