R Shiny ggplot bar and line charts with dynamic variable selection and y axis to be percentages

与世无争的帅哥 提交于 2019-11-28 02:24:00

To properly group variables for plotting, geom_bar requires that the x values be numeric and the fill values be factors or that the argument group be used to explicitly specify grouping variables. However, plotly throws an error when group is used. The approach below converts x variables to integer and fill variables to factor so that they are properly grouped. This retains the use of geom_bar to calculate the percentages.

First, however, I wonder if mydata is specified correctly. Given that the data is a mix of character and integer, cbind(Location, Brand, Year, Q1, Q2) gives a character matrix which is then converted to a data.table where all variables are character mode. In the code below, I've defined mydata directly as a data.table but have converted Q1 to character mode so that mydata contains a mix of character and numeric.

The approach used below is to create a new data frame, plotdata, containing the x and fill data. The x data is converted to numeric, if necessary, by first making it a factor variable and then using unclass to get the factor integer codes. The fill data converted to a factor. plotdata is then used generate the ggplot plot which is then displayed using plotly. The code includes a couple of other modifications to improve the appearance of the chart.

EDIT

The code below has been updated to show the name of the row variable beneath it's bar. Also the percentage and count for each bar are only shown when the mouse pointer hovers above the bar.

 library("shiny")
  library("ggplot2")
  library("scales")
  library(plotly)
  library(data.table)

  Location <- sample(1:5,100,replace = T)
  Brand <- sample(1:3,100,replace = T)
  Year <- rep(c("Year 2014","Year 2015"),50)
  Q1 <- sample(1:5,100,replace = T)
  Q2 <- sample(1:5,100,replace = T)
  Q3 <- sample(seq(1,3,.5), 100, replace=T)
  mydata <- data.table(Location,Brand,Year,Q1,Q2, Q3)
#
# convert Q1 to character for demonstation purposes  
#
    mydata$Q1 <- as.character(mydata$Q1)

  ui <- shinyUI(fluidPage(
    sidebarPanel(
      fluidRow(
        column(10,
               div(style = "font-size: 13px;", selectInput("rowvar", label = "Select Row Variable", 
                                                           choices=colnames(mydata)))),
        tags$br(),
        tags$br(),
        column(10,
               div(style = "font-size: 13px;", selectInput("columnvar", label="Select Column Variable", 
                                                           choices=colnames(mydata))))
        )
    ),
    tabPanel("First Page"),
    mainPanel(tabsetPanel(id='charts',
                          tabPanel("charts",tags$b(tags$br("Graphical Output" )),tags$br(),plotlyOutput("plot1"))
    )
    )
  ))
  server <- shinyServer(function(input, output,session){
    updateTabsetPanel(session = session
                      ,inputId = 'myTabs')
    observe({
      updateSelectInput(session, "rowvar", choices = colnames(mydata), selected=colnames(mydata)[1])
    })
    observe({
      updateSelectInput(session, "columnvar", choices = colnames(mydata), selected=colnames(mydata)[2])
    })
    output$plot1 <- renderPlotly({
#
#   create data frame for plotting containing x variables as integer and fill variables as factors
#   
      if(is.numeric(get(input$rowvar)))  {
        rowvar_brks <- sort(unique(get(input$rowvar)))
        rowvar_lbls <- as.character(rowvar_brks)
        plotdata <- data.frame(get(input$rowvar), factor(get(input$columnvar)) )
      }
      else {
        rowvar_factors <- factor(get(input$rowvar))
        rowvar_brks <- 1:nlevels(rowvar_factors)
        rowvar_lbls <- levels(rowvar_factors)
        plotdata <- data.frame(unclass(rowvar_factors), factor(get(input$columnvar)) )
      }
      colnames(plotdata) <- c(input$rowvar, input$columnvar)
      validate(need(input$rowvar,''),
               need(input$columnvar,''))
      col_width <- .85*mean(diff(rowvar_brks))
      sp <- ggplot(plotdata, aes_(x = as.name(input$rowvar), fill = as.name(input$columnvar))) +
        geom_bar( aes(y= ..prop..), stat="count", position=position_dodge(width=col_width)) +
        geom_text(aes( label = paste(scales::percent(..prop..),"<br>", "count:",..count..,"<br>"),  y= ..prop.. + .01),
                  stat= "count", position=position_dodge(width=col_width), size=3, alpha=0) +
        labs(x= input$rowvar, y = "Percent", fill=input$columnvar) +
        scale_y_continuous(labels=percent) +
        scale_x_continuous(breaks=rowvar_brks, labels=rowvar_lbls)
        ggplotly(sp, tooltip="none")
      })
  })

  shinyApp(ui = ui, server = server)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!