为什么不根据反应数据框更新条形图?

时间:2018-05-18 01:56:13

标签: r ggplot2 shiny reactive-programming

问题

尽管两者共享相同的反应数据框,为什么条形图与我的应用程序中的表格中显示的数据不匹配?

概述

我目前正在df安排iris数据框 - reactive expression使用单选按钮的输入并根据base::switch()排列数据。之后,df以两种形式显示:条形图和表格。

问题是条形图没有响应单选按钮,而表格却没有。我想要的输出是条形图按照升序/降序排列 - 基于单选按钮 - 与表格的排列方式相同。

对于为什么会发生这种情况以及如何解决这个问题的任何澄清都将非常感激!

Screenshot of App

代码

# load necessary package
library( shiny )
library( tidyverse )

# create UI
ui <- fluidPage(
  title = "Reactive Programming"
  , plotOutput( outputId = "my.barplot" )
  , radioButtons( inputId = "direction"
                  , label = "Arrange the data:"
                  , choices = c("Ascending", "Descending")
                  , selected = "Descending"
                  , inline = TRUE )
  , tableOutput( outputId = "my.table" )
)

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

  # arrange iris in ascending/descending order based on the "Sepal.Length" column
  df <- reactive({
    switch( EXPR = input$direction
            , "Ascending" = iris %>% arrange( Sepal.Length ) 
            , "Descending" = iris %>% arrange( desc( Sepal.Length ) ) )
  })

  # plot df()
  output$my.barplot <- renderPlot({
    ggplot( data = df() ) +
      geom_bar( aes( x = Species
                     , y = Sepal.Length )
                , stat = "identity" )
  })

  # show df()
  output$my.table <- renderTable({
    df()
  })
}

# run App
shinyApp( ui = ui, server = server )

# end of script #

会话信息

R version 3.4.4 (2018-03-15)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS High Sierra 10.13.2

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] forcats_0.3.0   stringr_1.3.0   dplyr_0.7.4     purrr_0.2.4     readr_1.1.1    
 [6] tidyr_0.8.0     tibble_1.4.2    ggplot2_2.2.1   tidyverse_1.2.1 shiny_1.0.5    

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.16     cellranger_1.1.0 pillar_1.2.1     compiler_3.4.4  
 [5] plyr_1.8.4       bindr_0.1.1      tools_3.4.4      digest_0.6.15   
 [9] lubridate_1.7.3  jsonlite_1.5     nlme_3.1-131.1   gtable_0.2.0    
[13] lattice_0.20-35  pkgconfig_2.0.1  rlang_0.2.0      psych_1.7.8     
[17] cli_1.0.0        rstudioapi_0.7   yaml_2.1.18      parallel_3.4.4  
[21] haven_1.1.1      bindrcpp_0.2     xml2_1.2.0       httr_1.3.1      
[25] hms_0.4.2        grid_3.4.4       glue_1.2.0       R6_2.2.2        
[29] readxl_1.0.0     foreign_0.8-69   modelr_0.1.1     reshape2_1.4.3  
[33] magrittr_1.5     scales_0.5.0     htmltools_0.3.6  rvest_0.3.2     
[37] assertthat_0.2.0 mnormt_1.5-5     colorspace_1.3-2 mime_0.5        
[41] xtable_1.8-2     httpuv_1.3.6.2   stringi_1.1.7    lazyeval_0.2.1  
[45] munsell_0.4.3    broom_0.4.3      crayon_1.3.4 

2 个答案:

答案 0 :(得分:1)

您无需更改ggplot中数据的顺序即可更改图表中的顺序。你必须在绘图函数中指定它:

我已创建if-else条件,以便在点击升序或降序时创建不同的图表。看看代码。我刚在geom_bar()函数

中添加了重新排序条件

代码:

library( shiny )
library( tidyverse )

# create UI
ui <- fluidPage(
  title = "Reactive Programming"
  , plotOutput( outputId = "my.barplot" )
  , radioButtons( inputId = "direction"
                  , label = "Arrange the data:"
                  , choices = c("Ascending", "Descending")
                  , selected = "Descending"
                  , inline = TRUE )
  , tableOutput( outputId = "my.table" )
)

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

  # arrange iris in ascending/descending order based on the "Sepal.Length" column
  df <- reactive({
    switch( EXPR = input$direction
            , "Ascending" = iris %>% arrange( Sepal.Length ) 
            , "Descending" = iris %>% arrange( desc( Sepal.Length ) ) )
  })

  # plot df()
  output$my.barplot <- renderPlot({
    if(input$direction=="Ascending")
      ggplot( data = df() ) +
      geom_bar( aes( x = Species
                     , y = Sepal.Length )
                , stat = "identity" )
    else if(input$direction=="Descending")
      ggplot( data = df() ) +
      geom_bar( aes( x = reorder(Species,-Sepal.Length)
                     , y = Sepal.Length )
                , stat = "identity" )
  })

  # show df()
  output$my.table <- renderTable({
    df()
  })
}

# run App
shinyApp( ui = ui, server = server )

如果需要,可以使用labs()重命名轴

输出闪亮的应用程序在Shiny Output

答案 1 :(得分:0)

概述

感谢@Gregor,我意识到我的错误并不是理解条形图顺序是由因子水平决定的。

虽然@Vedha Viyash的回答确实有效,但我通过使用dplyr::mutate()设置df()$Species中的级别来合并@ Gregor的建议,以使用stats::reorder()改变df()$Speciesdf()$Sepal.Length

通过不重复构造output$my.barplot内的绘图对象来尊重D.R.Y主体。

Screenshot of shiny app

# load necessary package
library( shiny )
library( tidyverse )

# create UI
ui <- fluidPage(
  title = "Reactive Programming"
  , plotOutput( outputId = "my.barplot" )
  , radioButtons( inputId = "direction"
                  , label = "Arrange the data:"
                  , choices = c("Ascending", "Descending")
                  , selected = "Descending"
                  , inline = TRUE )
  , tableOutput( outputId = "my.table" )
)

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

  # arrange iris in ascending/descending order based on the "Sepal.Length" column
  df <- reactive({
    switch( EXPR = input$direction
            , "Ascending" = iris %>% arrange( Sepal.Length ) %>% mutate( Species = reorder( x = Species, X = Sepal.Length ) )
            , "Descending" = iris %>% arrange( desc( Sepal.Length ) ) %>% mutate( Species = reorder( x = Species, X = desc( Sepal.Length ) ) ) )
  })

  # plot df()
  output$my.barplot <- renderPlot({
    ggplot( data = df() ) +
      geom_bar( aes( x = Species
                     , y = Sepal.Length )
                , stat = "identity" )
  })

  # show df()
  output$my.table <- renderTable({
    df()
  })
}

# run App
shinyApp( ui = ui, server = server )

# end of script #