Home > Software engineering >  How to make the variable to aggregate data frame columns by reactive?
How to make the variable to aggregate data frame columns by reactive?

Time:12-16

In the below MWE code and as shown in the image below, the aggregate() function is used to sum columns in a data frame. I'd like the user to be able to choose which variable to aggregate by, either Period_1 or Period_2 via clicking the radio button. Currently the below is coded only for Period_1.

How would I modify the $Period... in each aggregate() function, to reflect the user radio button input? So the user can also aggregate by Period 2 in this example.

MWE code:

library(shiny)

data <- data.frame(Period_1=c("2020-01","2020-02","2020-03","2020-01","2020-02","2020-03"),
                   Period_2=c(1,2,3,3,1,2),
                   ColA=c(10,20,30,40,50,60),
                   ColB=c(15,25,35,45,55,65)
                   )

ui <- 
  fluidPage( 
    
    h3("Data table:"),
    tableOutput("data"),
    h3("Sum the data table columns:"),
    radioButtons(
      inputId = 'vetaDataView2',
      label = NULL,
      choices = c('By period 1','By period 2'),
      selected = 'By period 1',
      inline = TRUE
    ),
    tableOutput("totals")  
  ) 
  

server <- function(input, output, session) {
  
  sumColA   <- aggregate(data$ColA~Period_1,data,sum)
  sumColB   <- aggregate(data$ColB~Period_1,data,sum)
  
  totals <- as.data.frame(c(sumColA, sumColB[2]))
  
  colnames(totals) <- c("Period_1","Sum Col A","Sum Col B")
  
  output$data <- renderTable(data)
  output$totals <- renderTable(totals)

}

shinyApp(ui, server)

enter image description here

CodePudding user response:

One option to achieve your desired result would be to use paste and as.formula to create the formula to aggregate your data base on the user input:

Note: To make my life a bit easier I switched to choiceNames and choiceValues.

library(shiny)

data <- data.frame(
  Period_1 = c("2020-01", "2020-02", "2020-03", "2020-01", "2020-02", "2020-03"),
  Period_2 = c(1, 2, 3, 3, 1, 2),
  ColA = c(10, 20, 30, 40, 50, 60),
  ColB = c(15, 25, 35, 45, 55, 65)
)

ui <-
  fluidPage(
    h3("Data table:"),
    tableOutput("data"),
    h3("Sum the data table columns:"),
    radioButtons(
      inputId = "vetaDataView2",
      label = NULL,
      choiceNames = c("By period 1", "By period 2"),
      choiceValues = c("Period_1", "Period_2"),
      selected = "Period_2",
      inline = TRUE
    ),
    tableOutput("totals")
  )


server <- function(input, output, session) {
  sumColA <- reactive({
    fmlaA <- as.formula(paste("ColA", input$vetaDataView2, sep = " ~ "))
    aggregate(fmlaA, data, sum)
  })

  sumColB <- reactive({
    fmlaB <- as.formula(paste("ColB", input$vetaDataView2, sep = " ~ "))
    aggregate(fmlaB, data, sum)
  })

  output$data <- renderTable(data)
  output$totals <- renderTable({
    totals <- as.data.frame(c(sumColA(), sumColB()[2]))

    colnames(totals) <- c(input$vetaDataView2, "Sum Col A", "Sum Col B")

    totals
  })
}

shinyApp(ui, server)
#> 
#> Listening on http://127.0.0.1:6231

  • Related