R Shiny: Как динамически добавлять произвольное количество входных виджетов
Я работаю над приложением Shiny, которое позволяет пользователю загружать свои собственные данные и фокусироваться на всех данных или подмножестве, предоставляя виджеты для фильтрации данных, описанные ниже на графике.Выбор входаПеременная 1«будет отображать все имена столбцов данных, загруженных пользователем, и выбор ввода»Значение"отобразит все уникальные значения соответствующего столбца, выбранного в"Переменная 1Msgstr "В идеале пользователь сможет добавить как можно больше таких строк ("Переменная X"+"Значение") насколько возможно с помощью какого-либо триггера, одной из возможностей является нажатие кнопки" Добавить еще ".
Возможное решениеПосмотрев в Интернете, я нашел одно многообещающее решение, данноеНик Карчеди вставлено ниже
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
})
})
Обратная сторонаКак указаноНик Карчеди Сам по себе все существующие входные виджеты будут сбрасываться нежелательно каждый раз, когда добавляется новый.
Многообещающее решение для поднабора / фильтрации данных в ShinyПо предложениюwarmoverflow,datatable
функция вDT Пакет предоставляет хороший способ фильтрации данных в Shiny. Ниже приведен минимальный пример с включенной фильтрацией данных.
library(shiny)
shinyApp(
ui = fluidPage(DT::dataTableOutput('tbl')),
server = function(input, output) {
output$tbl = DT::renderDataTable(
iris, filter = 'top', options = list(autoWidth = TRUE)
)
}
)
Если вы собираетесь использовать его в своем приложении Shiny, есть некоторые важные аспекты, которые стоит отметить.
Тип фильтровальной коробкиДля числовых столбцов / столбцов даты / времени: ползунки диапазона используются для фильтрации строк в диапазонахДля столбцов фактора: входные данные выбора используются для отображения всех возможных категорийДля символьных столбцов: используются обычные поля поискаКак получить отфильтрованные данныеПредположим, что выходной идентификатор таблицыtableId
использоватьinput$tableId_rows_all
как индексы строк на всех страницах (после того как таблица отфильтрована по поисковым строкам).Обратите внимание, чтоinput$tableId_rows_all
возвращает индексы строк на всех страницах для DT (> = 0.1.26). Если вы используете версию DT на регулярной основеinstall.packages('DT')
возвращаются только индексы текущей страницыУстановитьDT (> = 0.1.26), обратитесь кСтраница GitHubШирина колонкиЕсли в данных много столбцов, ширина столбца и ширина поля фильтра будут узкими, что затруднит просмотр текста в виде отчета.ВотЕще предстоит решитьНесмотря на некоторые известные проблемы,datatable
вDT Пакет является перспективным решением для подмножества данных в Shiny. Сам вопрос, а именно, как динамически добавлять произвольное количество входных виджетов в Shiny, тем не менее, интересен и также сложен. Пока люди не найдут хороший способ ее решить, я оставлю этот вопрос открытым :)
Спасибо!