Взаимозависимый каскад фильтров в R Shiny — updatePickerInput

#r #shiny #user-input #shinydashboard #shiny-server

Вопрос:

У меня есть 4 PickerInputs в приложении R Shiny, и на выходе получается отфильтрованный кадр данных из этих входных данных. Иногда эти входные данные выбираются, а иногда нет (значит, не применяется никакой фильтр).

Проблема: я хочу, чтобы все эти входные данные были каскадированы путем выбора друг друга.

 column(width=2, id="filters",
       
       shinyWidgets::pickerInput(
         inputId = "filter_a",
         label = 'Filter A',
         choices = c(""),
         multiple = FALSE),
       
       shinyWidgets::pickerInput(
         inputId = "filter_b",
         label = 'Filter B',
         choices = c(""),
         multiple = FALSE),
       
       shinyWidgets::pickerInput(
         inputId = "filter_c",
         label = 'Filter C',
         choices = c(""),
         multiple = FALSE),
       
       shinyWidgets::pickerInput(
         inputId = "filter_d",
         label = 'Filter D',
         choices = c(""),
         multiple = FALSE)
       )
 

Сервер:
Способ написания этих взаимозависимых каскадных фильтров «если бы иначе» выглядит не очень хорошо. Это определенно не оптимизированный код. Как я могу написать его как функцию?

Мне нужно, чтобы каждый фильтр наблюдал за остальными 3 фильтрами и обновлял варианты.

Пример обновления «фильтра C»:

 observeEvent(c(input$filter_a, input$filter_b, input$filter_d),
             
             {updatePickerInput(session = session,
                                inputId = 'filter_c',
                                
                                choices = if(input$filter_a==" All" amp; input$filter_b == " All" amp; input$filter_d == " All"){sort(c(" All", unique(df$column_c)))
                                }else if(input$filter_a ==" All" amp; input$filter_b == " All" amp; input$filter_d != " All"){sort(c(" All", unique(df$column_c[df$column_d==input$filter_d])))
                                }else if(input$filter_a ==" All" amp; input$filter_b != " All" amp; input$filter_d == " All"){sort(c(" All", unique(df$column_c[df$column_b==input$filter_b])))
                                }else if(input$filter_a !=" All" amp; input$filter_b == " All" amp; input$filter_d == " All"){sort(c(" All", unique(df$column_c[df$column_a==input$filter_a])))
                                }else if(input$filter_a ==" All" amp; input$filter_b != " All" amp; input$filter_d != " All"){sort(c(" All", unique(df$column_c[df$column_b==input$filter_b amp; df$column_d==input$filter_d])))
                                }else if(input$filter_a !=" All" amp; input$filter_b == " All" amp; input$filter_d != " All"){sort(c(" All", unique(df$column_c[df$column_a==input$filter_a amp; df$column_d==input$filter_d])))
                                }else if(input$filter_a !=" All" amp; input$filter_b != " All" amp; input$filter_d == " All"){sort(c(" All", unique(df$column_c[df$column_a==input$filter_a amp; df$column_b==input$filter_b])))
                                }else{sort(c(" All", unique(df$column_c[df$column_a==input$filter_a amp; df$column_b==input$filter_b amp; df$column_d==input$filter_d])))},
                                selected = c(" All"))
             })
 

column_a, column_b, column_c и column_d-это 4 столбца фильтра в моем df, на основе которых я выбираю filter_a, filter_b, filter_c, filter_d соответственно.

Комментарии:

1. вам следует подумать об использовании uiOutput() и. renderUI()

2. используйте case_when() вместо стольких ifelse

Ответ №1:

Возможно, это было бы немного лучше

 observeEvent(c(input$filter_a, input$filter_b, input$filter_d), {
   
  if(input$filter_a==" All") {fa <- unique(df$column_a)} else fa <- input$filter_a
  if(input$filter_b==" All") {fb <- unique(df$column_b)} else fb <- input$filter_b
  if(input$filter_d==" All") {fd <- unique(df$column_d)} else fd <- input$filter_d

  choices <- c(" All", unique(df$column_c[df$column_a %in% fa amp; df$column_b %in% fb amp; df$column_d %in% fd]))
  updatePickerInput(session = session, inputId = 'filter_c', choices = choices, selected = c(" All"))

})