如何根据菜单选择缩小R Shiny中的菜单?

ebdffaop  于 2023-01-10  发布在  其他
关注(0)|答案(2)|浏览(139)

我想根据菜单选项缩小显示给用户的菜单选项。因此,如果用户选择4中的"cyl",他们会看到选中的"4"框,然后只有基于该过滤器可供选择的"gear"复选框可用。

library(shiny)
library(data.table)
server = function(input, output) {
  filtered_data <- reactive({ 
    data <- as.data.table(mtcars)
    if (!is.null(input$cyl)) {data <- data[input$cyl == cyl  ]}
    if (!is.null(input$gear)){data <- data[input$gear == gear]}
    return(data)
  })
  
  output$table <- renderTable(filtered_data())
  output$cyl_choices <- renderUI({
    unique_cyl  <- unique(filtered_data()$cyl)
    unique_gear <- unique(filtered_data()$gear)
    return(tagList(
      checkboxGroupInput("cyl", "Number of cylinders:", unique_cyl),
      checkboxGroupInput("gear", "Gear:", unique_gear)
    )
    )
  }
  )
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      uiOutput("cyl_choices")
    ),
    mainPanel(
      tableOutput("table")
    )
  )
)

shinyApp(ui, server)

我在R Shiny中发现的是菜单立即将"Cyl"的复选框重置为空。
[编辑]
更一般地说,我希望在任何一个框中都有一个选项,以限制剩下的框中的选项。当我使用下面的代码根据建议进行第二次选择时,一切都重置了。

library(shiny)
library(data.table)

data <- as.data.table(mtcars)[, 
                              c("cyl", "vs", "am", "gear", "carb") := 
                                lapply(.SD, as.integer),
                              .SDcols = c("cyl", "vs", "am", "gear", "carb")]

`%|%` <- function(a, b) {
  if (is.null(a)) b else a
}

menu  <- function(x){
   sort(unique(x))
}
server <- function(input, output, session) {
  get_cyl <- reactive({
    input$cyl %|% data[, menu(cyl)]
  })
  
  get_gear <- reactive({
    input$gear %|% data[,menu(gear)]
  })
  
  get_carb <- reactive({
    input$carb %|% data[,menu(carb)]
  })
  
  get_cyl_choices <- reactive({
    data[gear %in% get_gear() &
         carb %in% get_carb(),
         unique(cyl)]   
  })

  get_gear_choices <- reactive({
    data[cyl  %in% get_cyl() &
         carb %in% get_carb(),
         unique(gear)]   
  })
  
  get_carb_choices <- reactive({
    data[cyl %in% get_cyl() &
        gear %in% get_gear(), 
         unique(carb)]   
  })
  
  output$table <- renderTable({
    data[cyl  %in% get_cyl()  & 
         gear %in% get_gear() &
         carb %in% get_carb() 
          ]
  })
  
  observeEvent(get_gear_choices(), {
    updateCheckboxGroupInput(session,
                             "gear",
                             choices = get_gear_choices())
  })
  
  observeEvent(get_cyl_choices(), {
    updateCheckboxGroupInput(session,
                             "cyl",
                             choices = get_cyl_choices())
  })
  
  observeEvent(get_carb_choices(), {
    updateCheckboxGroupInput(session,
                             "carb",
                             choices = get_carb_choices())
  })
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput("cyl",  "Cyl:",  data[, menu(cyl)]),
      checkboxGroupInput("gear", "Gear:", data[, menu(gear)]),
      checkboxGroupInput("carb", "Carb:", data[, menu(carb)])
    ),
    mainPanel(
      tableOutput("table")
    )
  )
)

shinyApp(ui, server)
dced5bon

dced5bon1#

问题是,一旦cyl发生变化,您就重新呈现gear输入,这反过来又会改变filtered_data,而filtered_data又会改变您的输入,因此一切都被重置。
话虽如此,我还是会将这两个checkboxGroupInputs分开,使用update*,而不是重新渲染(但这是一个品味问题,我觉得只更改一个方面比重新渲染整个输入“更便宜”,但我没有这方面的基准测试)。
长话短说,下面是一个工作示例:

library(shiny)
library(data.table)

data <- as.data.table(mtcars)[, 
                              c("cyl", "vs", "am", "gear", "carb") := 
                                lapply(.SD, as.integer),
                              .SDcols = c("cyl", "vs", "am", "gear", "carb")]

`%|%` <- function(a, b) {
  if (is.null(a)) b else a
}

server <- function(input, output, session) {
  get_cyl <- reactive({
    input$cyl %|% data[, unique(cyl)]
  })
  
  get_gear_choices <- reactive({
    data[cyl %in% get_cyl(), unique(gear)]   
  })
  
  get_gear <- reactive({
    input$gear %|% get_gear_choices()
  })
  
  output$table <- renderTable({
    data[cyl %in% get_cyl() & gear %in% get_gear()]
  })
  
  observeEvent(get_gear_choices(), {
    updateCheckboxGroupInput(session,
                             "gear",
                             choices = get_gear_choices())
  })
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput("cyl", "Number of cylinders:", data[, unique(cyl)]),
      checkboxGroupInput("gear", "Gear:", data[, unique(gear)])
    ),
    mainPanel(
      tableOutput("table")
    )
  )
)

shinyApp(ui, server)

s6fujrry

s6fujrry2#

在为这些菜单纠结了几个月之后,我意识到我不知道它们是如何工作的,我假设update函数是用来修改现有checkbox对象的一个或多个属性的,其余的将保持不变(包括选择)。但是看起来你必须完全指定属性。因此,最近使我的程序崩溃的是忽略了包含提示文本和选项和选择。当我采用上面的通用示例并确保包含相同的提示文本并指定选择时,事情按计划进行。2谢谢你的帮助。3我从你如何修改数据列和过滤中学到了一些东西!4下面是工作代码:

library(shiny)
library(data.table)

data <- as.data.table(mtcars)[, 
                              c("cyl", "vs", "am", "gear", "carb") := 
                                lapply(.SD, as.integer),
                              .SDcols = c("cyl", "vs", "am", "gear", "carb")]

`%|%` <- function(a, b) {
  if (is.null(a)) b else a
}

menu  <- function(x){
   sort(unique(x))
}
server <- function(input, output, session) {
  get_cyl <- reactive({
    input$cyl %|% data[, menu(cyl)]
  })
  
  get_gear <- reactive({
    input$gear %|% data[,menu(gear)]
  })
  
  get_carb <- reactive({
    input$carb %|% data[,menu(carb)]
  })
  
  get_cyl_choices <- reactive({
    data[gear %in% get_gear() &
         carb %in% get_carb(),
         unique(cyl)]   
  })

  get_gear_choices <- reactive({
    data[cyl  %in% get_cyl() &
         carb %in% get_carb(),
         unique(gear)]   
  })
  
  get_carb_choices <- reactive({
    data[cyl %in% get_cyl() &
        gear %in% get_gear(), 
         unique(carb)]   
  })
  
  output$table <- renderTable({
    data[cyl  %in% get_cyl()  & 
         gear %in% get_gear() &
         carb %in% get_carb() 
          ]
  })
  
  observeEvent(get_gear_choices(), {
    updateCheckboxGroupInput(session,
                             "gear",
                             "Gear:",
                             choices = get_gear_choices(),
                             selected=input$gear)
  })
  
  observeEvent(get_cyl_choices(), {
    updateCheckboxGroupInput(session,
                             "cyl",
                             "Cyl",
                             choices = get_cyl_choices(),
                             selected=input$cyc)
  })
  
  observeEvent(get_carb_choices(), {
    updateCheckboxGroupInput(session,
                             "carb",
                             "Carb",
                             choices = get_carb_choices(),
                             selected=input$carb)
  })
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput("cyl",  "Cyl:",  data[, menu(cyl)]),
      checkboxGroupInput("gear", "Gear:", data[, menu(gear)]),
      checkboxGroupInput("carb", "Carb:", data[, menu(carb)])
    ),
    mainPanel(
      tableOutput("table")
    )
  )
)

shinyApp(ui, server)

相关问题