Shiny Dashboard Not Responsive + Axes Not Displaying

Hello,

I am working on a straight forward US elections dashboard. The particular issue I'm stuck on involves a slider that controls a bar chart created with ggplot. The dashboard displays without errors, but I have 2 issues:

1.) The axis shows the column header names instead of the continuous variable.
2.) The slider bar is not updating the bar chart.

I have no idea why this is happening. Here is a reproducible example:


library(shiny)
library(shinydashboard)
library(ggplot2)
library(plotly)


year <- c(1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016,2020)
dem_ev <- c(303,486,191,17,297,49,13,111,370,379,266,251,365,332,227,306)
rep_ev <- c(219,52,301,520,240,489,525,426,168,159,271,286,173,206,304,232)

df <- data.frame(cbind(year,dem_ev,rep_ev))


# Define UI for application
ui <- fluidPage(
    dashboardPage(
        dashboardHeader(title=""),
        dashboardSidebar(
            sidebarMenu(
                menuItem("National Results",
                         tabName = "nat_results",
                         icon=icon("flag-usa")
                )
                
            )
        ),
        dashboardBody(
            tabItems(
                tabItem(
                    tabName = "nat_results",
                    fluidRow(
                        sliderInput("slider",
                                    "Choose an election year:",
                                    min=1960, max=2020, step=4,value=2020,sep=""
                                    )
                    ),
                    fluidRow(
                        align='center',
                        plotlyOutput("elec_votes_bar")
                        
                    )
                    
                )))))

# Define server logic 
server <- function(input, output) {

    filtered_data=reactive({
        filter=subset(df,year==input$year_select)
        return(filter)
    })
    
    output$elec_votes_bar <-renderPlotly({
        
        p<-ggplot(data=filtered_data(), aes(x=c('Republican','Democrat'), 
                                   y=c("Rep_EV","Dem_EV"),
                                   fill=c("#999999", "#E69F00"))) +
            geom_bar(stat="identity")+
            coord_flip()+
            theme(legend.position="none")+
            ylab('Electoral Votes')+xlab('')
        p
        
    })
}

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

Can someone help point me in the right direction? Thank you!

year_select appears only once in the code. So , it doesn't relate to anything. You can't use what you haven't defined.

1 Like

Hi @nirgrahamuk ! Thanks for the response! You are absolutely right that I forgot to define year_select - just a copy and paste error when making my reproducible example.

When I place year_select back in as defined:
year_select = unique(df$year)

there is no change in the plot. Am I doing something wrong with the slider? Still stuck on this.

Your slider input is called "slider" but you are referring to input$year_select in your reactive. Rename the slider to year_select?

1 Like

Thanks @schienstockd ! I updated the reactive component to read as:

filter = subset(df, year==input$slider)

I think that helped me get past all the dumb errors I was having, but now the latest error I'm getting is more at the root of the problem.

Aesthetics must be either length 1 or the same as the data (1): x, y and fill

I think ggplot is expecting one x , one y, and one fill since I'm filtering to one row at a time. But I'm trying to pass in two at a time since the two bars I want on the chart are two separate columns.

Is there a way around this that makes ggplot behave or a way I can manipulate my data to conform to ggplot's rules?

You have to think about tables a bit different. Put your values into individual rows with identifier columns rather then the values from different identifiers into columns.

You can transform your dataframe with something like this:

library(tidyverse)

df <- data.frame(cbind(year, dem_ev, rep_ev)) %>%
  rename(Democrat = dem_ev, Republican = rep_ev) %>%
  pivot_longer(!year, names_to = "party", values_to = "votes")

It is helpful to test data preparation and plotting in Markdown files rather than directly in shiny.

Then the full example

library(shiny)
library(shinydashboard)
library(ggplot2)
library(plotly)
library(tidyverse)


year <- c(1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016,2020)
dem_ev <- c(303,486,191,17,297,49,13,111,370,379,266,251,365,332,227,306)
rep_ev <- c(219,52,301,520,240,489,525,426,168,159,271,286,173,206,304,232)

df <- data.frame(cbind(year, dem_ev, rep_ev)) %>%
  rename(Democrat = dem_ev, Republican = rep_ev) %>%
  pivot_longer(!year, names_to = "party", values_to = "votes")

# set factors
df$party <- factor(df$party, levels = c("Democrat", "Republican"))

# Define UI for application
ui <- fluidPage(
  dashboardPage(
    dashboardHeader(title=""),
    dashboardSidebar(
      sidebarMenu(
        menuItem(
          "National Results",
          tabName = "nat_results",
          icon = icon("flag-usa")
        )
        
      )
    ),
    dashboardBody(
      tabItems(
        tabItem(
          tabName = "nat_results",
          fluidRow(
            sliderInput(
              "year_select",
              "Choose an election year:",
              min = 1960, max = 2020, step = 4 ,value = 2020
            )
          ),
          fluidRow(
            align = 'center',
            plotlyOutput("elec_votes_bar")
            )
          )
      )
    )
  )
)

# Define server logic 
server <- function(input, output) {
  
  filtered_data <- reactive({
    df %>% filter(year == input$year_select)
  })
  
  output$elec_votes_bar <-renderPlotly({
    p1 <- ggplot(
      data = filtered_data(),
      aes(x = party, y = votes, fill = party)) +
      scale_fill_manual(values = c("#999999", "#E69F00")) +
      geom_bar(stat = "identity") +
      coord_flip() +
      theme(legend.position = "none") +
      ylab('Electoral Votes') +
      xlab('') +
      ylim(0, max(df$votes))
    
    p1
  })
}

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

Thank you @schienstockd ! This is what I needed!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.