R Brilhante: Como anexar dinamicamente um número arbitrário de widgets de entrada
Estou trabalhando em um aplicativo brilhante que permite ao usuário fazer upload de seus próprios dados e se concentrar em todos os dados ou em um subconjunto, fornecendo widgets de filtragem de dados descritos no gráfico abaixo
Depois de pesquisar on-line, encontrei uma solução promissora dada porNick Carchedi colado abaixo
ui.R
library(shiny)
shinyUI(pageWithSidebar(
# Application title
headerPanel("Dynamically append arbitrary number of inputs"),
# Sidebar with a slider input for number of bins
sidebarPanel(
uiOutput("allInputs"),
actionButton("appendInput", "Append Input")
),
# Show a plot of the generated distribution
mainPanel(
p("The crux of the problem is to dynamically add an arbitrary number of inputs
without resetting the values of existing inputs each time a new input is added.
For example, add a new input, set the new input's value to Option 2, then add
another input. Note that the value of the first input resets to Option 1."),
p("I suppose one hack would be to store the values of all existing inputs prior
to adding a new input. Then,", code("updateSelectInput()"), "could be used to
return inputs to their previously set values, but I'm wondering if there is a
more efficient method of doing this.")
)
))
server.R
library(shiny)
shinyServer(function(input, output) {
# Initialize list of inputs
inputTagList <- tagList()
output$allInputs <- renderUI({
# Get value of button, which represents number of times pressed
# (i.e. number of inputs added)
i <- input$appendInput
# Return if button not pressed yet
if(is.null(i) || i < 1) return()
# Define unique input id and label
newInputId <- paste0("input", i)
newInputLabel <- paste("Input", i)
# Define new input
newInput <- selectInput(newInputId, newInputLabel,
c("Option 1", "Option 2", "Option 3"))
# Append new input to list of existing inputs
inputTagList <<- tagAppendChild(inputTagList, newInput)
# Return updated list of inputs
inputTagList
})
})
A desvantagemComo apontado porNick Carchedi ele próprio, todos os widgets de entrada existentes serão indesejáveis redefinidos toda vez que um novo for adicionado.
Uma solução promissora para subconjunto / filtragem de dados no ShinyComo sugerido porwarmoverflow, adatatable
função emDT O pacote fornece uma boa maneira de filtrar os dados no Shiny. Veja abaixo um exemplo mínimo com a filtragem de dados ativada.
library(shiny)
shinyApp(
ui = fluidPage(DT::dataTableOutput('tbl')),
server = function(input, output) {
output$tbl = DT::renderDataTable(
iris, filter = 'top', options = list(autoWidth = TRUE)
)
}
)
Se você for usá-lo em seu aplicativo Shiny, há alguns aspectos importantes que vale a pena notar.
Tipo de caixa de filtragemPara colunas numéricas / data / hora: controles deslizantes de intervalo são usados para filtrar linhas dentro de intervalosPara colunas de fatores: as entradas selecionadas são usadas para exibir todas as categorias possíveisPara colunas de caracteres: caixas de pesquisa comuns são usadasComo obter os dados filtradosSuponha que o ID de saída da tabela sejatableId
, usarinput$tableId_rows_all
como os índices de linhas em todas as páginas (após a tabela ser filtrada pelas cadeias de pesquisa).Por favor note queinput$tableId_rows_all
retorna os índices de linhas em todas as páginas para DT (> = 0.1.26). Se você usa a versão DT regularmenteinstall.packages('DT')
, apenas os índices da página atual são retornadosPara instalarDT (> = 0.1.26), consulte suaPágina GitHubLargura da colunaSe os dados tiverem muitas colunas, a largura da coluna e a largura da caixa de filtro serão estreitas, o que dificulta a visualização do texto como relatórioaquiAinda a ser resolvidoApesar de alguns problemas conhecidos,datatable
noDT O pacote é uma solução promissora para o subconjunto de dados no Shiny. A questão em si, isto é, como anexar dinamicamente um número arbitrário de widgets de entrada no Shiny, no entanto, é interessante e também desafiadora. Até que as pessoas encontrem uma boa maneira de resolvê-lo, deixarei esta pergunta em aberto :)
Obrigado!