闪亮:checkboxGroupInput 的条件面板和条件列表

Shiny: Conditional Panel and Conditional List of checkboxGroupInput

我想创建一个闪亮的应用程序来绘制美国总统初选的最新 pollstR 图表。用户应该能够 select 政党(民主党或众议员)、候选人和举行初选(或党团会议)的州。

我遇到三个问题:

  1. 基于 selected 政党(Dem 或 Rep),用户应该得到下一个 checkboxGroupInput,其中只有民主党或共和党候选人出现。我尝试用条件面板解决这个问题。但是,我不能两次使用 "Candidate" 作为 Widget 的名称(稍后在 server.R 中我需要 input$Candidate)。我该如何解决?

  2. 根据 selected 党(同样是民主党或众议员),用户应该得到所有州的列表,其中初选和党团会议到现在已经举行。目前,我列出了我之前定义的所有美国州(因此,如果我想绘制没有可用民意调查的州的结果,我会出错)。有没有办法从 server.R 部分生成的数据集中获取状态列表(那里称为 polls$state,但我不能使用它,因为 ui.R 现在不"polls").

  3. 我使用 ggplot 和 facet_wrap 函数(有两列)将结果绘制为 bar-charts。我选择的州越多,地块就越小。有没有办法设置绘图的高度并在主面板中插入垂直滚动条?

这是 UI 的代码:

shinyUI(fluidPage(
    titlePanel("2016 Presidential primaries"),

    sidebarLayout(position = "right",
            sidebarPanel(
                    helpText("Choose between Democratic (Dem) and Republican (Rep)
                             Primaries and Caucuses:"),

                    selectInput("party", 
                                label = "Dem or Rep?",
                                choices = c("Dem", "Rep",
                                selected = "Dem")),

                    conditionalPanel(
                            condition = "input.party == 'Dem'",
                            checkboxGroupInput("Candidate", label = h4("Democratic Candidates"), 
                                               choices = list("Clinton" = "Clinton", "Sanders" = "Sanders"),
                                               selected = NULL)),

                    conditionalPanel(
                            condition = "input.party == 'Rep'",
                            checkboxGroupInput("Candidate", label = h4("Republican Candidates"), 
                                               choices = list("Bush" = "Bush", "Carson" = "Carson", "Christie" = "Christie",
                                                              "Cruz" = "Cruz", "Kasich" = "Kasich", "Rubio" = "Rubio",
                                                              "Trump" = "Trump"),
                                               selected = NULL)),

                    checkboxGroupInput("state",
                            label = "Select State",
                            choices = states,
                            inline = TRUE,
                            selected = NULL)
            ),

            mainPanel(
                    tabsetPanel(
                            tabPanel("Plot", plotOutput("plot")), 
                            tabPanel("Table", tableOutput("table"))
                    )
            )


    )
))

这里是 server.R 的代码:

### getting and cleaning the data for the shiny app-----------------------------

# load pollstR-package to get Huffpost opinion polls
require(pollstR)

# load dplyr and tidyr for data wrangling
require(dplyr)
require(tidyr)

# load ggplot2 for plotting
require(ggplot2)

# download 2016 GOP presidential primaries
repPoll <- pollstr_charts(topic='2016-president-gop-primary', showall = TRUE)

# extract and combine columns needed
choice <- repPoll$estimates$choice
value <- repPoll$estimates$value
election <- repPoll$estimates$slug
party <- repPoll$estimates$party

rep.df <- data_frame(election, choice, value, party)


# extract and combine slug and state info to add list of US state abbreviations
election <- repPoll$charts$slug
state <- repPoll$charts$state

r.stateAbb <- data_frame(election, state)

# join both data frames based on slug
rep.df <- left_join(rep.df, r.stateAbb, by = "election")

## download 2016 DEM presidential primaries
demPoll <- pollstr_charts(topic='2016-president-dem-primary', showall = TRUE)

# extract and combine columns needed
choice <- demPoll$estimates$choice
value <- demPoll$estimates$value
election <- demPoll$estimates$slug
party <- demPoll$estimates$party

dem.df <- data_frame(election, choice, value, party)

# extract and combine slug and state info to add list of US state abbreviations
election <- demPoll$charts$slug
state <- demPoll$charts$state

d.stateAbb <- data_frame(election, state)

# join both data frames based on slug
dem.df <- left_join(dem.df, d.stateAbb, by = "election")

# combine dem and rep datasets
polls <- bind_rows(dem.df, rep.df)

polls$party <- as.factor(polls$party)
polls$state <- as.factor(polls$state)
polls$choice <- as.factor(polls$choice)


shinyServer(function(input, output) {

        df <- reactive({
                polls %>% filter(party %in% input$party) %>% filter(choice %in% input$Candidate) %>%
                        filter(state %in% input$state)
        })

       # generate figures
        output$plot <- renderPlot({
                validate(
                        need(input$party, "Please select a party"),
                        need(input$Candidate, "Please choose at least one candidate"),
                        need(input$state, "Please select at least one state")
                )
                p <- ggplot(df())
                p <- p + geom_bar(aes(x = choice, weight = value, fill = choice),
                                  position = "dodge", width=.5) 

                # colorize bars based on parties        
                if (input$party == "Dem")
                        p <- p + scale_fill_brewer(palette = "Blues", direction = -1)
                if (input$party == "Rep")
                        p <- p + scale_fill_brewer(palette = "Reds", direction = -1)

                # add hlines for waffle-design
                p <- p + geom_hline(yintercept=seq(0, 100, by = 10), col = 'white') +
                        geom_text(aes(label = value, x = choice, y = value + 1), position = position_dodge(width=0.9), vjust=-0.25) +
                        # facet display
                        facet_wrap( ~ state, ncol = 2) +
                        # scale of y-axis
                        ylim(0, 100) + 
                        # delete labels of x- and y-axis
                        xlab("") + ylab("") +
                        # blank background and now grids and legend
                        theme(panel.grid.major.x = element_blank(), panel.grid.major.y = element_blank(),
                              panel.grid.minor.y = element_blank(),
                              panel.background = element_blank(), legend.position = "none")
                print(p)    
        }

        )

        # Generate a table view of the data
        output$table <- renderTable({
                polls %>% filter(party %in% input$party) %>% filter(choice %in% input$Candidate) %>%
                        filter(state %in% input$state)
        })

}
)

这里是问题 1 和 2 的解决方案:

ui.R中,将conditionalPanelcheckboxGroupInput替换为

  uiOutput('candidates'),
  uiOutput('states')

server.R中,在df <- reactive({....前添加如下代码。请注意,您需要将某些 input$Candidate 代码更改为小写。

  observeEvent(input$party, {
    output$candidates <- renderUI({
      checkboxGroupInput(
        "candidate",
        ifelse(input$party == 'Dem', "Democratic Candidates", "Republican Candidates"),
        as.vector(unique(filter(polls,party==input$party)$choice))
      )
    })
  })

  observeEvent(input$candidate, {
    output$states <- renderUI({
      states_list <- as.vector(unique(filter(polls, party==input$party & choice==input$candidate)$state))
      checkboxGroupInput(
        "state",
        "Select state",
        # Excluding national surveys
        states_list[states_list!="US"]
      )
    })
  })

对于问题 3,将 df reactive 更改为 observe,然后根据选择的州数设置绘图高度。同时更改此行 p <- ggplot(df)

  observe({      
    df <- polls %>% filter(party %in% input$party) %>% filter(choice %in% input$candidate) %>% filter(state %in% input$state)
    height <- ceiling(length(input$state) / 2) * 200
    output$plot <- renderPlot({
      #Your plot code
    }, height=height)
  })