Quero exibir uma tabela onde o usuário pode filtrar dinamicamente a tabela com base em uma ou mais colunas, com os diferentes filtros "respeitando" uns aos outros. Isso é semelhante a algumas outras perguntas (por exemplo, aqui , aqui e aqui ).
A exibição inicial deve ser a tabela completa. As colunas que podem ser usadas para filtragem são categóricas, e vários valores são permitidos para cada coluna. As escolhas nos menus suspensos devem refletir os valores disponíveis no momento, portanto, devem ser atualizadas com base nas seleções feitas em outros menus. Não há hierarquia pai/filho inerente às colunas/menus/filtros: o usuário deve ser capaz de começar a filtrar de qualquer menu. Finalmente, se nada foi selecionado em um menu específico, esse filtro deve ser desconsiderado (em vez de filtrar tudo).
No final das contas, isso também precisa ser dimensionado para ~10 filtros, então tentando evitar soluções muito detalhadas. Com base em tudo isso e perguntas/respostas relacionadas, cheguei ao seguinte. Bits individuais parecem funcionar durante o teste, mas não quando colocados juntos:
library(shiny)
ui = fluidPage(
fluidRow(selectizeInput("cyl_select", "Select cylinder:","",multiple = TRUE), #using `selectizeInput` because real data requires adjusting the `maxOptions` setting
selectizeInput("gear_select","Select gear:", "",multiple = TRUE),
selectizeInput("carb_select","Select carburator:", "",multiple = TRUE)),
fluidRow(DTOutput("filtered_table")))
server <- function(input, output, session) {
df_mtcars = reactive({mtcars})
#filter based on user input
df_mtcars_filt = reactive({df_mtcars() %>%
{if (!is.null(input$cyl_select)) filter(.,cyl %in% input$cyl_select) else . } %>% #piped if/else: only filter if input$[selection_var] contains meaningful values, otherwise pass data unaltered
{if (!is.null(input$gear_select)) filter(.,gear %in% input$gear_select) else . } %>%
{if (!is.null(input$carb_select)) filter(.,carb %in% input$carb_select) else . }
})
#render
output$filtered_table = renderDT( df_mtcars_filt())
#update the choice list
observe({updateSelectizeInput(session,"cyl_select",choices = sort(unique(df_mtcars_filt()$cyl)))})
observe({updateSelectizeInput(session,"gear_select",choices = sort(unique(df_mtcars_filt()$gear)))})
observe({updateSelectizeInput(session,"carb_select",choices = sort(unique(df_mtcars_filt()$carb)))})
}
# run the app
shinyApp(ui = ui,
server = server,
options = list(launch.browser = TRUE))
Se você tem o requisito para uma solução que deve ser escalável para um número maior de entradas (aqui: colunas para filtrar o quadro de dados), então uma abordagem adequada poderia ser confiar em
lapply
. Abaixo, isso é, por exemplo, usado para gerar oselectizeInput
e para gerar oobserveEvent()
nessas entradas.Além disso
lapply
, fiz alguns ajustes no código fornecido por você, por exemplo, umselected
argumento é fornecido dentro doupdateSelectizeInput
. Também é preciso ter cuidado para evitar dependências circulares entre odataTable
e as atualizações de entrada.