firmo23
firmo23

Reputation: 8454

Create plotly grouped bar chart with dynamic number of groups in a shiny app

I have the shiny app below in which the user is able to select one or both dataframes and then based on the other filters to create a bar plot which will display the values of one or both dataframes. Now I have not connected it to the widgets in order to display what I want to achieve. It confuses me how to give the dataframes df1 and df2 to the plot_ly() and add_trace() functions together or one at a time.

library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(dplyr)
library(plotly)
shinyApp(
    ui = dashboardPagePlus(
        header = dashboardHeaderPlus(title = "Social Media Metrics", titleWidth = 320
                                     
        ),
        sidebar = dashboardSidebar(width = 320,
                                   checkboxGroupInput("checkGroup", label = "Select Dataset", 
                                                      choices = list("df1", "df2"),
                                                      selected = "df1"),
                                   checkboxGroupInput("checkGroup2", label = "Select Social Network", 
                                                      choices = list("FACEBOOK", "INSTAGRAM"),
                                                      selected = "FACEBOOK"),
                                   radioButtons("radio", label = "Choose type of values",
                                                choices = list("Absolute", "Percentages" ), 
                                                selected = "Absolute"),
                                   uiOutput("x30"),
                                   uiOutput("x16"),
                                   uiOutput("value")
                                   
                                   
        ),
        body = dashboardBody(
            plotlyOutput("plot")
        )
        
        
    ),
    server = function(input, output) {
       
        page<-c("ONE","TWO","THREE")
        network<-c("INSTAGRAM","FACEBOOK","FACEBOOK")
        av<-c(3.5,7.2,8.7)
        growth<-c(5,7,9)
        av2<-c(3.5,7.2,8.7)
        growth2<-c(5,7,9)
        df1<-data.frame(page,network,av,growth,av2,growth2)
        
        page<-c("ONE","TWO","THREE")
        network<-c("INSTAGRAM","FACEBOOK","FACEBOOK")
        av<-c(4.5,7.9,8.7)
        growth<-c(5,6,9)
        av2<-c(3.5,9.2,8.7)
        growth2<-c(5,43,9)
        df2<-data.frame(page,network,av,growth,av2,growth2)
        
        output$x30<-renderUI({
            if("df1" %in% input$checkGroup){
                new<-subset(df1, network %in% input$checkGroup2)
                pickerInput(
                    inputId = "x3"#The colname of selected column
                    ,
                    label = "Select Profile-df1" #The colname of selected column
                    ,
                    choices = as.character(new$page)#all rows of selected column
                    ,
                    multiple = TRUE,options = list(`actions-box` = TRUE)
                    
                )
            }
            else{
                return(NULL)
            }
            
        })
        output$x16<-renderUI({
            if("df2" %in% input$checkGroup){
                new<-subset(df2, network %in% input$checkGroup2)
                pickerInput(
                    inputId = "x6"#The colname of selected column
                    ,
                    label = "Select Profile-df2" #The colname of selected column
                    ,
                    choices = as.character(new$page)#all rows of selected column
                    ,
                    multiple = TRUE,options = list(`actions-box` = TRUE)
                    
                )
            }
            else{
                return(NULL)
            }
            
        })
        output$value<-renderUI({
            if(input$radio=="Absolute"){
                pickerInput(
                    inputId = "val"
                    ,
                    label = "Select Absolut Value" 
                    ,
                    choices = c("growth","growth2")#all rows of selected column
                    ,
                    multiple = F,options = list(`actions-box` = TRUE)
                    
                )
            }
            else{
                pickerInput(
                    inputId = "val"
                    ,
                    label = "Select Percentage Value" 
                    ,
                    choices = c("av","av2")#all rows of selected column
                    ,
                    multiple = F,options = list(`actions-box` = TRUE)
                    
                )
            }
            
        })
        output$plot<-renderPlotly({
            fig <- plot_ly(df1, x = ~page, y = ~growth, type = 'bar', name = 'growth')
            fig <- fig %>% add_trace(df2,y = ~growth, name = 'growth')
            fig <- fig %>% layout(yaxis = list(title = 'Count'), barmode = 'group')
            
            fig
        })
    }
)

Upvotes: 0

Views: 653

Answers (1)

YBS
YBS

Reputation: 21349

A reactive dataframe dfa() gives the selected data from either or both dataframes. Now, plotly requires some work. Please note that working with variables within dfa() gives some errors as both df1 and df2 are defined within the server and are available in output$plot, and hence, you may need to use dfa()$id, etc.

library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(dplyr)
library(plotly)
shinyApp(
  ui = dashboardPagePlus(
    header = dashboardHeaderPlus(title = "Social Media Metrics", titleWidth = 320
                                 
    ),
    sidebar = dashboardSidebar(width = 320,
                               checkboxGroupInput("checkGroup", label = "Select Dataset", 
                                                  choices = list("df1", "df2"),
                                                  selected = "df1"),
                               checkboxGroupInput("checkGroup2", label = "Select Social Network", 
                                                  choices = list("FACEBOOK", "INSTAGRAM"),
                                                  selected = "FACEBOOK"),
                               radioButtons("radio", label = "Choose type of values",
                                            choices = list("Absolute", "Percentages" ), 
                                            selected = "Absolute"),
                               uiOutput("x30"),
                               uiOutput("x16"),
                               uiOutput("value")
                               
    ),
    body = dashboardBody(
      plotlyOutput("plot") , DTOutput("tb1")
    )
    
    
  ),
  server = function(input, output) {
    
    page<-c("ONE","TWO","THREE")
    network<-c("INSTAGRAM","FACEBOOK","FACEBOOK")
    av<-c(3.5,4.2,8.7)
    growth<-c(4,7,9)
    av2<-c(3.5,7.2,4.7)
    growth2<-c(4,7,9)
    id <- rep("df1",3)
    df1<-data.frame(page,network,av,growth,av2,growth2,id)
    
    page<-c("ONE","TWO","THREE")
    network<-c("INSTAGRAM","FACEBOOK","FACEBOOK")
    av<-c(4.5,7.9,8.7)
    growth<-c(5,4,8)
    av2<-c(3.5,9.2,6.7)
    growth2<-c(5,4,9)
    id <- rep("df2",3)
    df2<-data.frame(page,network,av,growth,av2,growth2,id)
    
    output$x30<-renderUI({
      if (is.null(input$checkGroup)) {
        return(NULL)
      }else if("df1" %in% input$checkGroup){
        new<-subset(df1, network %in% input$checkGroup2)
        pickerInput(
          inputId = "x3" #The rownames of selected column
          ,
          label = "Select Profile-df1" #The colname of selected column
          ,
          choices = as.character(new$page) #all rows of selected column
          ,
          multiple = TRUE,options = list(`actions-box` = TRUE)
          
        )
      }
      else{
        return(NULL)
      }
      
    })
    output$x16<-renderUI({
      if (is.null(input$checkGroup)) {
        return(NULL)
      }else if( "df2" %in% input$checkGroup){
        new2<-subset(df2, network %in% input$checkGroup2)
        pickerInput(
          inputId = "x6" #The rownames of selected column
          ,
          label = "Select Profile-df2" #The colname of selected column
          ,
          choices = as.character(new2$page) #all rows of selected column
          ,
          multiple = TRUE,options = list(`actions-box` = TRUE)
          
        )
      }
      else{
        return(NULL)
      }
      
    })
    output$value<-renderUI({
      if(req(input$radio)=="Absolute"){
        pickerInput(
          inputId = "val"
          ,
          label = "Select Absolut Value" 
          ,
          choices = c("growth","growth2") #all rows of selected column
          ,
          multiple = F, options = list(`actions-box` = TRUE)
          
        )
      }else if(req(input$radio)=="Percentages"){
        pickerInput(
          inputId = "val"
          ,
          label = "Select Percentage Value" 
          ,
          choices = c("av","av2")#all rows of selected column
          ,
          multiple = F,options = list(`actions-box` = TRUE)
          
        )
      } else {return(NUL)}
      
    })
    
    dfa <- reactive({
      req(input$val)
      if (is.null(input$checkGroup)) {return(NULL)}
      if (input$checkGroup == "df1" | length(input$checkGroup) == 2){
        df11 <- df1 %>% filter(page %in% req(input$x3) & network %in% req(input$checkGroup2))
      }else df11 <- NULL
      if (input$checkGroup == "df2" | length(input$checkGroup) == 2){
        df22 <- df2 %>% filter(page %in% req(input$x6) & network %in% req(input$checkGroup2)) 
      }else df22 <- NULL
      
      if (is.null(df11) & is.null(df22)) {return(NULL)
      }else {
        if (is.null(df11)){df <- df22
        }else if (is.null(df22)){df <- df11
        }else { df <- rbind(df11,df22) }
        df <- df %>%  transform(y=df[[as.name(input$val)]], x=page)
      }
      df
    })
    
    output$tb1 <- renderDT(dfa())
    
    output$plot<-renderPlotly({
      if (is.null(dfa())) return(NULL)
      xvar <- unique(dfa()$page)
      xform <- list(categoryorder = "array",
                    categoryarray = xvar)  ## to get the bars in the order you wish to display
      fig <- plot_ly() 
     
      fig <- fig %>% add_trace( dfa() , x = ~x, y = ~y, type='bar', name='growth', fill=x, color=dfa()$id)
      fig <- fig %>% layout(xaxis = list(xform, title="Page"), 
                            yaxis = list(title = 'Count'), barmode = 'group')
      fig
    })
  }
)

Upvotes: 1

Related Questions