Search code examples
shinyuser-inputsummary

Shiny App for generating a summary table of columns based on user input


I am trying to generate a shiny app where a summary table can be generated for a column selected by the user from a drop down of columns. Dataframe used is a sample dataset.



library(shiny)
library(dplyr)

df <- data.frame(grouping_letter = c('A', 'A', 'B', 'B', 'C', 'C'), 
                 grouping_animal = c('Cat', 'Dog', 'Cat', 'Dog', 'Cat', 'Dog'),
                 value = c(1,2,3,4,5,6))

df <- df %>% mutate(
    grouping_letter = as.character(grouping_letter),
    grouping_animal = as.character(grouping_animal))

# Define UI for application that summarizes a table
ui <- fluidPage(

    selectInput(inputId ="column",
                label = "Choose Column for Summary",
                choices = names(df),
                selected = "grouping_letter"),

    tableOutput('table')
)

# Define server logic required to output summary table
server <- function(input, output) {
    groupvar <- reactive({input$column})
    cols <- c('value', unlist(groupvar))
    dt_f <- df[,cols] %>%
        group_by_at(2) %>%
        summarise (value = n(), yield = round(mean(value)*100, 1)) %>%
        mutate(Pct_of_value = paste0(round(100 * value/sum(value), 0), "%"))
    output$table <- renderTable(dt_f)
}

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

I getting an error: Warning: Error in .subset: invalid subscript type 'list' I am using R 3.6 and RStudio on windows


Solution

  • There are two problems

    • groupvar is reactive, so you don't want to unlist a reactive value.
    • You need to use groupvar() to get values inside a reactive object. However, in order to run groupvar(), you need to do it within active reactive context: like observe, observeEvent or renderXXX. To give you a not very precise idea is that functions in shiny that allow you to use function({}) expressions.

    See my code below, this should be what you want. Notice how I use renderTable.

    library(shiny)
    library(dplyr)
    
    df <- data.frame(grouping_letter = c('A', 'A', 'B', 'B', 'C', 'C'), 
                     grouping_animal = c('Cat', 'Dog', 'Cat', 'Dog', 'Cat', 'Dog'),
                     value = c(1,2,3,4,5,6))
    
    df <- df %>% mutate(
        grouping_letter = as.character(grouping_letter),
        grouping_animal = as.character(grouping_animal))
    
    # Define UI for application that summarizes a table
    ui <- fluidPage(
    
        selectInput(inputId ="column",
                    label = "Choose Column for Summary",
                    choices = names(df),
                    selected = "grouping_letter"),
    
        tableOutput('table')
    )
    
    # Define server logic required to output summary table
    server <- function(input, output) {
        groupvar <- reactive({input$column})
    
        output$table <- renderTable({
            df[, c('value', groupvar())] %>%
                group_by_at(2) %>%
                summarise (value = n(), yield = round(mean(value)*100, 1)) %>%
                mutate(Pct_of_value = paste0(round(100 * value/sum(value), 0), "%"))
        })
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)