How to aggregate on a reactive Shiny data frame

shiny

#1

I want to have a output table in the UI that has a conditional column sum based on the text of “Column 3”.

Here is my example code:

library(shiny)
runApp(list(
ui=pageWithSidebar(headerPanel("Adding entries to table"),
             sidebarPanel(textInput("text1", "Column 1", "66"),
                          textInput("text2", "Column 2", "100"),
                          textInput("text3", "Column 3", "Tony"),
                          actionButton("update", "Update Table")),
             mainPanel(tableOutput("table1"))),
server=function(input, output, session) {
values <- reactiveValues()
values$df <- data.frame(Column3 = character(), 
                    Column1 = numeric(0), 
                    Column2 = numeric(0),
                    stringsAsFactors = FALSE)
newEntry <- observe({
if(input$update > 0) {
newLine <- isolate(c(input$text3, input$text1, input$text2))
isolate(values$df[nrow(values$df) + 1,] <- c(input$text3, 
input$text1, input$text2))
  }
})
output$table1 <- renderTable({values$df})
}))

If you click on the “Update Table” button twice, the output table that I would like to see it is:
Tony 132 200

The names in “Column 3” will be different depends on the input value from the sidebar. The output table should observe that, and then return all the names with sum of “Column 1” and sum of “Column 2” under that name.

I tried to create a new data frame using the aggregate function on the values$df, but it is not working.


#2

I did this by introducing a new reactive expression representing the aggregated data frame, and used dplyr’s group_by and summarise functions to perform the aggregation.

Your code also was storing the numeric columns as character vectors (they were starting out as numeric but getting coerced to characters), so I also changed your observer to use the rbind function and converted the inputs to numeric.

HTH.

library(shiny)
library(dplyr)
runApp(list(
  ui=pageWithSidebar(headerPanel("Adding entries to table"),
    sidebarPanel(textInput("text1", "Column 1", "66"),
      textInput("text2", "Column 2", "100"),
      textInput("text3", "Column 3", "Tony"),
      actionButton("update", "Update Table")),
    mainPanel(tableOutput("table1"))
  ),
  server = function(input, output, session) {
    values <- reactiveValues()
    values$df <- data.frame(Column3 = character(), 
      Column1 = numeric(0), 
      Column2 = numeric(0),
      stringsAsFactors = FALSE)
    newEntry <- observeEvent(input$update, {
      values$df <- rbind(values$df,
        data.frame(stringsAsFactors = FALSE,
          Column3 = input$text3,
          Column1 = as.numeric(input$text1),
          Column2 = as.numeric(input$text2)
        )
      )
    })
    
    aggregated <- reactive({
      values$df %>%
        group_by(Column3) %>%
        summarise(Column2 = sum(Column2), Column1 = sum(Column1))
    })
    
    output$table1 <- renderTable({
      aggregated()
    })
  }
))

#3

Hi jcheng,

Thank you so much for your help! The aggregate function you created are exactly what I am looking for! Tons of thanks!!


#4

This is really helpful article. I have searching this and with simple example it is explained.
I tried this, for editable tables it will not work. if any cell edited by user then it should be explicitly handled.
Thank You.