R Shiny:如何对数据帧进行子集和排序?



我是新来的闪亮。我正在尝试将数据帧和数据帧子集,但遇到错误消息:

"在响应性消费者之外无法访问响应性值'xx';

谁能告诉我为什么?

设计思想是:(1)让用户选择他们想要查看的子组,我尝试使用reactiveValues()命令完成,但失败了,然后(2),在该子组内的延迟操作,根据关键变量对数据进行排序。下面是代码,谢谢你的帮助:

library(shiny)
library(tidyverse)
data(iris)
ui <- fluidPage(
navbarPage(
title = "Test",
tabsetPanel(
tabPanel(
"Tab 3, subset and then sort",
sidebarLayout(
sidebarPanel(
selectInput("xx", "species:", choices = unique(iris$Species), selected = "setosa"),
actionButton("click", "sort")
),
mainPanel(
tableOutput("table3")
)
)
)
)
)
)
server <- function(input, output) {
rv <- reactiveValues(
#### This line caused a problem whenever I added %>% dplyr::filter ####
df3 = iris %>% dplyr::filter(Species == !!input$xx)
)
observeEvent(input$click, {
rv$df3 <- rv$df3[order(rv$df3$Sepal.Length), ]
})
output$table3 <- renderTable({
rv$df3
})
}
# Run the application
app <- shinyApp(ui = ui, server = server)
runApp(app)
  1. reactiveValues应该用作reactive/observe块中更新/求值的值列表。这里用错了,我想你应该用reactiveeventReactive

  2. 双邦!!rlang中的NSE(非标准评估)(以及大部分的tidyverse)相关,但这不是你在这里做的。在您的示例中,input$xxcharacter,在这种情况下,您可以直接将其与Species == input$xx进行比较。

  3. 有时,根据应用程序的启动情况,在输入具有有效值之前触发响应,而不是NULL。这会在闪亮的界面中导致错误和故障,并且可以通过使用req来避免。

  4. 不幸的是,你不能在它之外使用reactive数据块。

这里有一个选择:

server <- function(input, output) {
rv_unsorted <- reactive({
req(input$xx)
dplyr::filter(iris, Species == input$xx)
})
rv_sorted <- reactive({
req(input$click)
dplyr::arrange(isolate(rv_unsorted()), Sepal.Length)
})
output$table3 <- renderTable({
rv_sorted()
})
}

另一个方法,效率较低(更贪婪,更懒惰),

server <- function(input, output) {
rv <- reactiveVal(iris)
observeEvent(input$xx, {
rv( dplyr::filter(iris, Species == input$xx) )
})
observeEvent(input$click, {
rv( dplyr::arrange(rv(), Sepal.Length) )
})
output$table3 <- renderTable({
rv()
})
}

这在逻辑上似乎更直接,但它将做比技术上必要的更多的工作。(observe块是贪婪的,尽可能快地触发,即使他们的工作没有被使用/注意到。reactive块是懒惰的,因为它们永远不会触发,除非有东西使用/需要它们。

编辑我纠正了之前的行为,它是:

  1. 加载iris,所有物种存在,存储在rv()
  2. 立即过滤,只显示setosa,存储在rv()
  3. 显示在表中
  4. 将选择器更改为新物种。
  5. 过滤rv()的内容,使框架中只有新物种。不幸的是,因为rv()的内容只是setosa,所以下一个过滤删除了所有行。

这意味着当前的observe序列(尽管它可能是贪婪和低效的)必须在某个时刻从一个新的帧开始,所以我改变了input$xx观察块,总是从iris开始。

最新更新