Adding and selecting dataframe columns in R Shiny

Viewed 629

I'm working on an R Shiny App that plots monthly percent changes in political party registrations. I'm still pretty new to interactive web apps (and Stack Overflow), and just haven't been able to find answers to these quesions -- thanks/sorry in advance.

In an older version of the app (here) I was able to let the user select the region, and I had manually put % monthly changes directly in the original dataframe.

What I'm trying to do now is enable the app to:

  1. Allow the user to choose/input a specific political party, which are each stored as columns in my df
  2. Then have the app itself calculate and add a new column with % monthly change for the selected party & region, so I don't have to do that manually for each party in the original df.

I can't figure out how to let the user select by party name / df column. I've tried:

selectizeInput(inputId = 'Party', label= 'Party',
                             choices = colnames(df_2016)

but that doesn't work.

I also have no clue how to do 2 lol.

Thanks in advance for any help you can provide; would realy appreciate if anyone could point me in the right direction or toward resources to learn how to do this. The relevant files are here if needed.

Here's the code for my UI and Server:

UI:

library(shiny)
library(shinydashboard)
library(ggplot2)
library(dplyr)
library(ggthemes)
library(shinythemes)
library(lubridate)

df_2016 = read.csv('df_2016.csv')
df_2020 = read.csv('df_2020.csv')

# Define UI for application
fluidPage(theme = shinytheme('cerulean'),
          
          # Application title
          titlePanel("NJ Voter Registration"),
          
          sidebarLayout(
              # Drop-down menu with region options
              
              mainPanel(
                  selectizeInput(inputId = 'County', label= 'Region',
                                 choices = df_2016$County),
            
              ),
              
              mainPanel(
                  tabsetPanel(
                      
                      tabPanel('Home',
                               "Data is sourced from the NJ Division of Elections Voter Registration Statistics Archive, which can be accessed at https://www.state.nj.us/state/elections/election-information-svrs.shtml",
                               "Please use the drop-down menu above to select whether to view statewide statistics, or data for a specific county.",
                      ),
                      
                      tabPanel('2016 Data',
                               'The dataframe for your selection is provided here.',
                               tableOutput('tableonesix')
                      ),

                      tabPanel('2020 Data',
                               'The dataframe for your selection is provided here.',
                               tableOutput('tabletwozero')
                      )
                      
                  )
              )
          )
          
)

Server:

library(shiny)
library(shinydashboard)
library(ggplot2)
library(dplyr)
library(ggthemes)
library(shinythemes)
library(lubridate)

df_2016 = read.csv('df_2016.csv')
df_2020 = read.csv('df_2020.csv')


function(input, output) {
    
    output$tableonesix=renderTable(
        df_2016 %>%
            filter(County==input$County)
    )
    
    output$tabletwozero=renderTable(
        df_2020 %>%
            filter(County==input$County)
    )
    
}
1 Answers

This sample app shows how it can be done.

  • Your idea using selecizeInput was correct. However, I would not recommend declaring the data frames as global variables. The usual approach would be to keep the data in the server and feed only the data we want to show to the client.
  • Use updateSelectizeInput to set the choices once the data frames have been loaded. The observerwill do that every time dfchanges.
  • Finally, renderTablefilters the relevant part of the data frame and sends it to the client.
library(shiny)

ui <- fluidPage(
    titlePanel("Party Sample"),

    sidebarLayout(
        sidebarPanel(
            selectizeInput("Party", "Party", choices = NULL),
            selectizeInput("County", label= "Region", choices = NULL),
        ),

        mainPanel(
           tableOutput("tableonesix")
        )
    )
)

# 
server <- function(input, output, session) {
  # DUMMY DATA
  df <- reactiveVal(data.frame(Democrats = 1:10, Republicans = 10:1, 
                               Libertarians = 1:10, GreenParty = 10:1,
                               County = sample(c("A", "B", "C"), 10, TRUE)))

  observe({
    # select only the party columns 1-4; 5 is the county column
    updateSelectizeInput(session, "Party", choices = colnames(df()[1:4])) 
    # Get counties without duplicates
    updateSelectizeInput(session, "County", choices = unique(df()$County))
  })
  
  output$tableonesix <- renderTable({
    # Do not run unless selects have a usable value
    req(input$Party, input$County)
    # Select: here in base R (not dplyr)
    df()[df()$County == input$County, input$Party]
  })
  
}

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