R Shiny ggplot条形图和折线图,动态变量选择,y轴为百分比

时间:2016-12-10 17:50:42

标签: r ggplot2 shiny data.table plotly

我正在学习Shiny,并希望得到我正在创建的应用程序的帮助。我正在创建一个应用程序,它将从用户获取动态输入,并应生成条形图和折线图。我设法创建了条形图,但它产生的结果不正确。

我要找的是在行中选择的变量应该是我的x轴,而y轴应该是百分比。规模为100%。 column变量应该是用于比较的变量,因为我使用的是position = "dodge"。我的数据很大,我创建了一个示例数据来描述情况。由于实际数据是data.table格式,我将样本数据存储为data.table。由于我不确定如何包含不是文件格式的数据,我首先创建它以便它在R环境中然后运行应用程序 -

    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)

    mydata <- as.data.table(cbind(Location,Brand,Year,Q1,Q2))

以下是我正在使用的 Shiny 代码 -

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

ui <- shinyUI(fluidPage(
  sidebarPanel(
    fluidRow(
      column(10,
             div(style = "font-size: 13px;", selectInput("rowvar", label = "Select Row Variable", ''))
      ),
      tags$br(),
      tags$br(),
      column(10,
             div(style = "font-size: 13px;", selectInput("columnvar", "Select Column Variable", ''))
      ))

  ),
  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 = (as.character(colnames(mydata))),selected = "mpg")
  })

  observe({
    updateSelectInput(session, "columnvar", choices = (as.character(colnames(mydata))),selected = "cyl")
  })

  output$plot1 <- renderPlotly({
    validate(need(input$rowvar,''),
             need(input$columnvar,''))
    ggplot(mydata, aes(x= get(input$rowvar))) + 
      geom_bar(aes(y = ..prop.., fill = get(input$columnvar)), position = "dodge", stat="count") +
      geom_text(aes( label = scales::percent(..prop..),
                     y= ..prop.. ), stat= "count", vjust = -.5) +
      labs(y = "Percent", fill=input$rowvar) +
      scale_y_continuous(labels=percent,limits = c(0,1))

  })

})

shinyApp(ui = ui, server = server)

如果您发现问题是 -

  1. 所有栏均为100%。比例未正确计算。不知道我哪里出错了。

  2. 如果我尝试使用group参数,则会给出错误说&#34;输入&#34;变量未找到。我尝试将小组作为group = get(input$columnvar)

  3. 我相信我需要重新构建折线图的数据。你能帮忙我如何动态重组data.table然后重新使用折线图。如何生成与折线图相同的条形图。

  4. 我正在使用renderplotly,因此我使用plotly的功能来显示鼠标移动/缩放等百分比。但是我可以在鼠标移动时看到输入$ variable。我怎样才能摆脱它并有正确的名字。

  5. 试图详细说明情况。建议一些解决方案。

    谢谢!

1 个答案:

答案 0 :(得分:1)

要为绘图正确分组变量,geom_bar要求x值为数字,fill值为因子或参数group用于明确指定分组变量。但是,plotly在使用group时会引发错误。以下方法将x变量转换为integerfill变量为factor,以便将它们正确分组。这保留了使用geom_bar来计算百分比。

然而,首先,我想知道是否正确指定了mydata。假设数据是字符和整数的混合,cbind(Location, Brand, Year, Q1, Q2)给出一个字符矩阵,然后将其转换为data.table,其中所有变量都是字符模式。在下面的代码中,我已将mydata直接定义为data.table,但已将Q1转换为字符模式,以便mydata包含字符和数字的混合。

下面使用的方法是创建一个包含plotdatax数据的新数据框fill。如果需要,x数据将转换为数字,首先使其成为因子变量,然后使用unclass获取因子整数代码。 fill数据已转换为因子。然后使用plotdata生成ggplot图,然后使用plotly显示。该代码包括一些其他修改,以改善图表的外观。

修改

以下代码已更新,以显示其下方行变量的名称。此外,只有当鼠标指针悬停在条形图上方时,才会显示每个条形图的百分比和计数。

 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)