我们创建了一个 Shiny 的应用程序,用户可以上传大型数据集(超过 200MB 的 RData 文件),也可以从我们这里选择一个。然后,用户可以在三个不同的选项卡中过滤数据(数字选项卡、类别选项卡)
所以目前我有 3 个 reactive
函数来达到这个目的。但缺点是该对象在内存中保存了 3 次。有没有更有效的方法来做到这一点?
请在下面找到一个简化的示例应用程序: 注意:在此应用程序中,每个选项卡只能看到 1 个过滤器。通常它更像是这样的:
My_Filtered_Data[Species %in% input$filter1 &
x %in% input$x &
y %in% input$y &
z %in% input$z] #etc.
我正在查看 reactiveValues
但无法真正找到它是如何工作的。
我不想将其置于 1 reactive
中的原因是,每次我更改其中一张纸上的其中一个过滤器时,整个过滤过程都会重新开始,这非常耗时。我希望拥有一个仅使用当时使用的过滤器进行更新的数据集。这就是我包含不同 react 的原因
## app.R ##
library(shinydashboard)
library(data.table)
CustomHeader <- dashboardHeader(title='datatest')
iris<-iris
ui <- function(request) {
dashboardPage(
CustomHeader,
## Sidebar content
dashboardSidebar(
sidebarMenu(
menuItem("filter1 & Import", tabName = "filter1", icon = icon("dashboard")),
menuItem("filter2", tabName = "filter2", icon = icon("th")),
menuItem("filter3", tabName = "filter3", icon = icon("th"))
)
),
## Body content
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "filter1",
fluidRow(box(width = 3,
selectInput(inputId = 'filter1','filter1:species',choices = unique(iris$Species))))
),
tabItem(tabName = "filter2",
fluidRow(box(width = 3,
sliderInput(inputId = 'filter2','filter2:Max.Sepal.Length',min = 0,max = 10,value = 10)
))
),
tabItem(tabName = "filter3",
fluidRow(box(width = 3,
sliderInput(inputId = 'filter3','filter3:Min.Sepal.Width',min = 0,max = 10,value = 0)
),
box(width=9,dataTableOutput('mydata')))
)
)
)
)
}
server <- function(input, output) {
My_Uploaded_Data <- reactive({
My_Uploaded_Data<-data.table(iris)
My_Uploaded_Data
})
My_Filtered_Data <- reactive({
My_Filtered_Data<-My_Uploaded_Data()
My_Filtered_Data[Species %in% input$filter1]
})
My_Filtered_Data2 <- reactive({
My_Filtered_Data2<-My_Filtered_Data()
My_Filtered_Data2[Sepal.Length < input$filter2]
})
My_Filtered_Data3 <- reactive({
My_Filtered_Data3<-My_Filtered_Data2()
My_Filtered_Data3[Sepal.Width > input$filter3]
})
output$mydata<-renderDataTable({
My_Filtered_Data3()
})
}
shinyApp(ui, server)
我希望像这样的东西可以在 reactiveValues
中工作
react_vals <- reactiveValues(data = NULL)
observe(react_vals$data <- MyLoadedData())
observe(react_vals$data <- react_vals$data[Species %in% input$filter1])
observe(react_vals$data <- react_vals$data[Sepal.Length < input$filter2])
observe(react_vals$data <- react_vals$data[Sepal.Width > input$filter3])
编辑:我还想包含书签:https://shiny.rstudio.com/articles/advanced-bookmarking.html看来你需要 reactiveValues
为此。因此,我放弃所有这些 reactives
/eventReactive
最佳答案
无需将数据集存储在 react 变量中,只需存储符合条件的行即可。这样,每个无功值仅在滤波器发生变化时才被替换;它们没有联系在一起。输出仅使用通过所有过滤器的行。
在程序顶部,将 iris
更改为 data.table
:
library(shinydashboard)
library(data.table)
CustomHeader <- dashboardHeader(title = 'datatest')
iris <- iris
setDT(iris) # Added
然后将其用于服务器逻辑:
server <- function(input, output) {
filter1_rows <- reactive({
iris[Species %in% input$filter1, which = TRUE]
})
filter2_rows <- reactive({
iris[Sepal.Length < input$filter2, which = TRUE]
})
filter3_rows <- reactive({
iris[Sepal.Width > input$filter3, which = TRUE]
})
output$mydata <- renderDataTable({
final_rows <- intersect(filter1_rows(), filter2_rows())
final_rows <- intersect(final_rows, filter3_rows())
iris[final_rows]
})
}
这使用了 data.table[...]
中经常被忽视的 which
参数,这意味着只应返回子集表的行号。
关于r - 如何在 Shiny 的应用程序中使用多个过滤器有效处理数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45344812/