selectizeInput根据另一个菜单中的选择过滤所有其他菜单(每次进行选择时)

时间:2018-07-31 15:39:28

标签: r shiny

我的数据看起来像数据集poses = poses_t() vrsystem.getDeviceToAbsoluteTrackingPose( openvr.TrackingUniverseStanding, 0, len(poses), poses) now = rospy.Time.now() transforms = [] # Hmd is always 0 matrix = poses[0].mDeviceToAbsoluteTracking hmd_pose = from_matrix_to_transform(matrix, now, "world", "hmd") transforms.append(hmd_pose) ,其中的列可能包含重复的值,但是每一行都是唯一的。
我的代码:

Orange

我的问题是这些列表能够选择多个输入(我想要),但是,我想首先显示所有菜单中的所有可用选项(它当前正在执行),但是我需要更改的是让它根据提供的唯一行数据集在选择之后(无论用户先进入哪个列表)立即开始过滤其他列表。
因此,如果用户转到第二个列表并选择树龄library(shiny) library(DT) library(data.table) d <- copy(Orange) col_names <- names(Orange) user_friendly_names <- c('TreeNumber', 'TreeAge', 'Circumference') ui <- fluidPage( sidebarLayout( sidebarPanel( h3("Filters:"), uiOutput("filters"), # Plot button fluidRow(column(2, align = "right", actionButton("plot_graph_button", "Plot"))) ), mainPanel(tableOutput("summary")) ) ) server <- function(input, output) { #### Create the filter lists for UI #### output$filters <- renderUI({ if(is.null(col_names)) return(NULL) lapply(1:length(col_names), function(i) { col <- paste0(col_names[i]) alias <- user_friendly_names[i] # Populate input with unique values from column selectizeInput(inputId = alias, label = paste(alias,':'), choices = c('All', unique(d[[col]])), selected = 'All', multiple = T) }) }) output$summary <- renderTable({ # Do not show a plot when the page first loads # Wait until the user clicks "Plot" button if (input$plot_graph_button == 0){ return() } # Update code below everytime the "Plot" button is clicked input$plot_graph_button isolate({ # Fresh copy of the full data set every time "Plot" button is clicked d <- copy(Orange) # Filter data based on UI for(f in 1:length(col_names)){ print(paste("This is loop # ", f)) if(eval(parse(text = paste0('is.null(input$',user_friendly_names[f],')')))){ # If the user deleted "All" but failed to pick anything else default to "All" - do not filter break }else{ if(eval(parse(text = paste0('input$',user_friendly_names[f]))) != "All"){ print("FALSE -- Input is not == ALL") d <- d[d[[col_names[f]]] == unlist(eval(parse(text = paste0('input$',user_friendly_names[f])))), ] }else{ print("TRUE -- Input is defaulted to ALL") } } } final_summary_table <<- d }) }) } shinyApp(ui = ui, server = server) ,则1004菜单应更改为TreeNumber-在这种情况下,请选择c(1, 2, 3, 4, 5)菜单应该更改为Circumference,然后如果他们选择c(115, 156, 108, 167, 125),则菜单会同时被TreeAgeTreeAge过滤,依此类推。

现在,代码的工作方式是它不会过滤任何内容,直到您单击“绘图”为止,因此用户可能会认为搜索将产生大量结果,而实际上可能不存在该组合。

这是一个很好的搜索示例,您可能会期望产生很多结果,但仅产生1行:

enter image description here

请注意::如果您不删除“全部”,即使您选择了其他选项,它也会返回“全部”,这是我打算与一些代码分开解决的一个缺陷。其他小的调整。

我还想提一提,我发现这篇文章Filter one selectInput based on selection from another selectInput?与我的相似,但是,他们以自上而下的方式处理菜单,而我将在用户选择哪个菜单方面更加灵活首先(我的也允许多个选择)。

1 个答案:

答案 0 :(得分:1)

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

  output$filters <- renderUI({
    # ...
  })

  lapply(seq_along(d), function(i) {
    observeEvent(input[[user_friendly_names[i]]], {
      for (j in seq_along(d)[-i]) {
        choices <- if ("All" %in% input[[user_friendly_names[i]]]) 
          unique(d[[j]]) else 
          unique(d[[j]][d[[i]] %in% input[[user_friendly_names[i]]]])
        choices <- c("All", choices)
        selected <- intersect(choices, input[[user_friendly_names[j]]])
        updateSelectInput(session = session, inputId = user_friendly_names[j], 
                          choices = choices, selected = selected)
      }
    })
  })

  observeEvent(input$plot_graph_button, {
    for (j in seq_along(d)) {
      updateSelectInput(session = session, inputId = user_friendly_names[j], 
                        choices = c("All", unique(d[[j]])), selected = "All")
    }
  })

  output$summary <- renderTable({
     # ...          
  })
}