2
votes

For a few days I've been working on an app with the shiny library and now I would like to test the new adaptations with the shinydashboard package. The problem is that my plot does not show up (render) in the tab that I would like it to appear when I set the inputs in the sidebar.

Using only the shiny package, I've set the following code, with no menu sidebar (as in shinydashboard):

library(shiny)
library(ggplot2)
library(dplyr)

rm(list=ls()); gc()

#functions to order the bar graph

reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) {
  new_x <- paste(x, within, sep = sep)
  stats::reorder(new_x, by, FUN = fun)
}

scale_x_reordered <- function(..., sep = "___") {
  reg <- paste0(sep, ".+$")
  ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...)
}

#setting example data 

sample_data = data.frame(Company_Name=c("Company 1","Company 2","Company 3",
                                        "Company 1","Company 2","Company 3",
                                        "Company 1","Company 2","Company 3"),
                         Profits_MM = c(20,100,80,
                                        45,120,70,
                                        50,110,130),
                         Sales_MM = c(200,800,520,
                                      300,1000,630,
                                      410,1150,1200),
                         Year=c(2016,2016,2016,
                                2017,2017,2017,
                                2018,2018,2018))


# UI
ui <- fluidPage(

  sidebarLayout(

    # Input(s)
    sidebarPanel(

      checkboxGroupInput(inputId = "sel_com",
                         label = "Company Selection:",
                         choices = c("Company 1","Company 2","Company 3"),
                         selected = "Company 1"),


      selectInput(inputId = "y", 
                  label = "Performance Variable",
                  choices = c("Profits (in Millions)" = "Profits_MM", 
                              "Sales (in Millions)" = "Sales_MM"),
                  selected = "Profits_MM"),


      sliderInput("year","Year Selection:",
                  min=2016,
                  max=2018,
                  value=c(2017,2018),
                  step=1)


    ),

    # Output(s)
    mainPanel(
      plotOutput(outputId = "barplot")
    )
  )
)

# Server
server <- function(input, output, session) {

  companies_sel <- reactive({

    req(input$sel_com)

    sample_data_gg = filter(sample_data, Company_Name %in% input$sel_com)
    #  print(sample_data_gg)
    sample_data_gg

  })

  year_sample <- reactive({

    req(input$year)
    sample_data_gg = sample_data
    if((input$year[2] - input$year[1])>1){

      Years = seq(input$year[1],input$year[2])

      sample_data_gg = filter(companies_sel(), Year %in% Years)

    }  

    if((input$year[2] - input$year[1])==1){

      sample_data_gg = filter(companies_sel(), Year %in% input$year)

    }
    #  print(sample_data_gg)
    sample_data_gg
  })


  output$barplot = renderPlot({

    sample_data_gg = year_sample()

    y <- input$y
    ggplot(data = sample_data_gg, aes(x=reorder_within(Company_Name, get( y ), Year), y = get( y ))) +
      geom_col(position="dodge", fill="darkred") +
      facet_wrap(Year~., scales = "free")  +
      scale_x_reordered() +
      theme(axis.text.x = element_text(angle = 60, hjust = 1))


  })

}

shinyApp(ui = ui, server = server)

This code works within the shiny package and shows the type of plot that I would like to show up in the app.

But if I change this coding for the shinydashboard package -- while setting the inputs inside the sidebar -- the plot does not show up and I'm trying to figure out why. Here it is the code:

library(shiny)
library(ggplot2)
library(dplyr)
library(shinydashboard)

reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) {
  new_x <- paste(x, within, sep = sep)
  stats::reorder(new_x, by, FUN = fun)
}

scale_x_reordered <- function(..., sep = "___") {
  reg <- paste0(sep, ".+$")
  ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...)
}

rm(list=ls()); gc()

sample_data = data.frame(Company_Name=c("Company 1","Company 2","Company 3",
                                        "Company 1","Company 2","Company 3",
                                        "Company 1","Company 2","Company 3"),
                         Profits_MM = c(20,100,80,
                                        45,120,70,
                                        50,110,130),
                         Sales_MM = c(200,800,520,
                                      300,1000,630,
                                      410,1150,1200),
                         Year=c(2016,2016,2016,
                                2017,2017,2017,
                                2018,2018,2018))


# UI
ui <- dashboardPage(
      dashboardHeader(title = "Dashboard Test"),
      dashboardSidebar(

      sidebarMenu(id="tab",
                  menuItem("Data Selection", tabName = "dc", icon = icon("dashboard"),
      checkboxGroupInput(inputId = "sel_com",
                         label = "Company Selection:",
                         choices = c("Company 1","Company 2","Company 3"),
                         selected = "Company 1"),
      selectInput(inputId = "y", 
                  label = "Performance Variable",
                  choices = c("Profits (in Millions)" = "Profits_MM", 
                              "Sales (in Millions)" = "Sales_MM"),
                  selected = "Profits_MM"),
      sliderInput("year","Year Selection:",
                  min=2016,
                  max=2018,
                  value=c(2017,2018),
                  step=1)))),


      dashboardBody(

        tabItems(
          # First tab content
          tabItem(tabName = "dc",

                  fluidRow(column(width=12,box(plotOutput("plot1")))


        )
      )
    )
  )
)


# Server
server <- function(input, output, session) {

  companies_sel <- reactive({

    req(input$sel_com)

    sample_data_gg = filter(sample_data, Company_Name %in% input$sel_com)
    #  print(sample_data_gg)
    sample_data_gg

  })

  year_sample <- reactive({

    req(input$year)
    sample_data_gg = sample_data
    if((input$year[2] - input$year[1])>1){

      Years = seq(input$year[1],input$year[2])

      sample_data_gg = filter(companies_sel(), Year %in% Years)

    }  

    if((input$year[2] - input$year[1])==1){

      sample_data_gg = filter(companies_sel(), Year %in% input$year)

    }
    #  print(sample_data_gg)
    sample_data_gg
  })


  output$barplot = renderPlot({

    sample_data_gg = year_sample()

    y <- input$y
    ggplot(data = sample_data_gg, aes(x=reorder_within(Company_Name, get( y ), Year), y = get( y ))) +
      geom_col(position="dodge", fill="darkred") +
      facet_wrap(Year~., scales = "free")  +
      scale_x_reordered() +
      theme(axis.text.x = element_text(angle = 60, hjust = 1))


  })

}

shinyApp(ui = ui, server = server)

I believe I might be missing some interaction between the barplot and the input selection in the sidebar, but I cannot figure exactly what is wrong.

1
Just to clarify: the server code is identical for both (?).Axeman
Yes. Maybe there is problem there.John Doe
I'm new into building shiny appsJohn Doe
Oh I don't know. Just trying to save people from trying to figure out if there is any difference.Axeman
That's exactly the issue. Take out rm(list=ls())); gc() from your code for the shinydashboard example and you should be good to go. As is, it's deleting your defined functions used to render the ggplot, which would cause errors and thus no ggplot to be displayed in the shiny appDave Gruenewald

1 Answers

4
votes

You actually had a few issues in your code that were collectively causing the issue:

First: The first was identified in the comments - your use of rm(list=ls()) was deleting functions that you needed later.

Second: Your plotOutput() was using the id "plot1" while your renderPlot was referring to "barplot". I assume that was a simple translation error from when you were switching over to shinydashboard. Make them the same and that will help.

Third: This was the more serious of the three. shinydashboard has a known issue, described very well here, where multiple elements within menuItem cause the loss of the attributes that link the content to tabItems. You can overcome that with a custom function that sets those values manually, and then wrap your menuItem calls in that function, taking care to specify the tabName in the function.

convertMenuItem <- function(mi,tabName) {
  mi$children[[1]]$attribs['data-toggle']="tab"
  mi$children[[1]]$attribs['data-value'] = tabName
  mi
}

Updated UI for your situation would look like this:

ui <- dashboardPage(
      ... #Other elements remain unchanged
      dashboardSidebar(
        sidebarMenu(
          convertMenuItem(menuItem("Data Selection", tabName = "dc", icon = icon("dashboard"),
              checkboxGroupInput(inputId = "sel_com",
                                label = "Company Selection:",
                                choices = c("Company 1","Company 2","Company 3"),
                                selected = "Company 1"),
              selectInput(inputId = "y", 
                                 label = "Performance Variable",
                                 choices = c("Profits (in Millions)" = "Profits_MM", 
                                             "Sales (in Millions)" = "Sales_MM"),
                                 selected = "Profits_MM"),
              sliderInput("year","Year Selection:",
                          min=2016,
                          max=2018,
                          value=c(2017,2018),
                          step=1)), tabName="dc")
        )
      ),
     ... #Other elements remain unchanged
     )

enter image description here