Tim*_*cht 4 memory r reactive-programming shiny data.table
我们创建了一个闪亮的应用程序,用户可以上传大数据集(RDB文件超过200MB),也可以从我们这里选择一个.然后有三个不同的选项卡,用户可以在其中过滤数据(数字选项卡,分类选项卡)
所以目前我有3个reactive功能来实现这个目的.但缺点是对象在内存中保留了三次.有没有更有效的方法来做到这一点?
请在下面找到一个简化的示例应用程序:注意:在此应用中,每个标签只能看到1个过滤器.通常它更像这样:
My_Filtered_Data[Species %in% input$filter1 &
x %in% input$x &
y %in% input$y &
z %in% input$z] #etc.
Run Code Online (Sandbox Code Playgroud)
我在看,reactiveValues但无法真正找到它是如何工作的.原因我不想让它在1中reactive是每次我更改其中一个工作表上的其中一个过滤器时,整个过滤过程再次启动,这非常耗时.我更希望有一个数据集只使用当时使用的过滤器进行更新.这就是我加入不同反应的原因
## 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)
Run Code Online (Sandbox Code Playgroud)
我希望像这样的东西可以工作 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])
Run Code Online (Sandbox Code Playgroud)
编辑:我也想包括书签:https://shiny.rstudio.com/articles/advanced-bookmarking.html似乎你需要reactiveValues它.所以我摆脱所有这些的另一个原因reactives/eventReactive
而不是将数据集存储在反应变量中,只需存储符合条件的行.这样,每个无功值只在滤波器改变时才被替换; 他们没有联系在一起.输出只使用通过所有过滤器的行.
在程序的顶部,更改iris为data.table:
library(shinydashboard)
library(data.table)
CustomHeader <- dashboardHeader(title = 'datatest')
iris <- iris
setDT(iris) # Added
Run Code Online (Sandbox Code Playgroud)
然后将其用于服务器逻辑:
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]
})
}
Run Code Online (Sandbox Code Playgroud)
这使用了经常被忽略的which参数data.table[...],这意味着只应返回子集化表的行号.
我认为你的问题与闪亮和/或反应式编程无关。这是一个“经典的时间与记忆”的情况。基本上来说,您只有两个选择:存储“部分”过滤的对象或不存储。
如果您确实存储它们,则会使用大量内存,但可以立即返回对象。如果没有,您只需要存储原始对象,但每次都必须再次过滤它。两者之间没有什么。您只是不能创建一个与原始对象不同(即过滤后的对象)但不占用额外内存的对象,即使使用reactiveValues.
当然,您可以进行权衡,例如为第一个过滤器创建中间对象并动态计算第二个和第三个过滤器,但这不会改变根本问题。
| 归档时间: |
|
| 查看次数: |
2926 次 |
| 最近记录: |