我是新来的闪亮。我正在尝试将数据帧和数据帧子集,但遇到错误消息:
"在响应性消费者之外无法访问响应性值'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)
-
reactiveValues
应该用作reactive
/observe
块中更新/求值的值列表。这里用错了,我想你应该用reactive
或eventReactive
。 -
双邦
!!
与rlang
中的NSE(非标准评估)(以及大部分的tidyverse)相关,但这不是你在这里做的。在您的示例中,input$xx
是character
,在这种情况下,您可以直接将其与Species == input$xx
进行比较。 -
有时,根据应用程序的启动情况,在输入具有有效值之前触发响应,而不是
NULL
。这会在闪亮的界面中导致错误和故障,并且可以通过使用req
来避免。 -
不幸的是,你不能在它之外使用
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
块是懒惰的,因为它们永远不会触发,除非有东西使用/需要它们。
编辑我纠正了之前的行为,它是:
- 加载
iris
,所有物种存在,存储在rv()
。 - 立即过滤,只显示
setosa
,存储在rv()
。 - 显示在表中
- 将选择器更改为新物种。
- 过滤
rv()
的内容,使框架中只有新物种。不幸的是,因为rv()
的内容只是setosa
,所以下一个过滤删除了所有行。
这意味着当前的observe
序列(尽管它可能是贪婪和低效的)必须在某个时刻从一个新的帧开始,所以我改变了input$xx
观察块,总是从iris
开始。