【问题标题】:Reactive variable triggered too soon (on app start up) in Shiny Dashboard在 Shiny Dashboard 中过早触发反应变量(在应用程序启动时)
【发布时间】:2019-08-14 15:55:06
【问题描述】:

我正在 Shiny 中构建一个包含大量学区数据的交互式地图/仪表板。目标是构建一个带有各种条件面板的侧边栏,当用户做出某些选择时,图层将显示在地图上,并且值框会显示在地图下方,并带有一些汇总的统计信息。如果您想尝试使用相同的数据重新创建问题,我正在使用这两个 shapefile(尽管在单独的脚本中我合并了其他数据并将“学校”保存为 csv w/lat&lng 列而不是 shp文件):

http://schoolsdata2-tea-texas.opendata.arcgis.com/datasets/059432fd0dcb4a208974c235e837c94f_0

schoolsdata2-tea-texas.opendata.arcgis.com/datasets/e115fed14c0f4ca5b942dc3323626b1c_0

第一个selectizeInput 提供 3 层:学区、邮政编码、县。选择“Districts”图层后,会弹出一个有条件的 Selectize 和一个可供选择的地区列表。选择一个学区后,会出现另一个条件面板,提供所选学区内的校区列表。

为了提供“校园”selectizeInput 的选项,我有一个 school_choices 反应变量,它可以拉取与所选学区一起列出的唯一校园名称列表。

问题似乎是在启动应用程序时,该变量在没有任何用户输入的情况下触发/触发该地区。 It also does not appear to be updating the selectizeInput when a district IS chosen.

我尝试将反应变量嵌套在 ObserveEvent 以及带有 if 语句的 Observe 函数中,但似乎正在发生同样的问题。

library(rgdal)
library(data.table)
library(readxl)
library(RPostgreSQL)
library(janitor)
library(rgeos)
library(here)
library(leaflet)
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinyBS)
library(shinydashboard)
library(dplyr)
library(DT)
library(mapview)
library(png)

poly_options<- c("Independent School Districts", "Youth Crime Data by County", "Employment Data by Zip Code")
district_data <- readOGR(here("source_data/districts.shp"))
campus_data <- read.csv(here("source_data/schools.csv"))
district_options <- sort(district_data@data$NAME)



ui <- fluidPage(
   useShinyjs(),
   useShinydashboard(),
   titlePanel("Awesome Title"),
   sidebarLayout(
      sidebarPanel(
        selectizeInput(inputId = "polygons", label = "Display Info Rich layers:",
                       choices = c("Choose one     " = "", as.character(poly_options)), multiple = TRUE),

        conditionalPanel(condition = "output.districts",
                         selectizeInput(inputId = "schdist", label = "Choose a District:", choices = district_options, 
                                        multiple = FALSE, options = list(placeholder = 'Select one', 
                                                                         onInitialize = I('function() { this.setValue(""); }')))),

        conditionalPanel(condition= "input.schdist", uiOutput("select_campus")),
)))

###

server <- function(input, output, session) {
  school_choices <- reactive({
    dist <- district_data[district_data@data$NAME == input$schdist, ]
    choices <- campus_data[(campus_data$DISTNAME ==  dist$NAME), ]
    choices <- choices$CAMPNAME
    return(choices)
    })

  output$districts <- reactive({ 
    if("Independent School Districts" %in% input$polygons) {
      return(TRUE)
    } else {
      return(NULL)
    } 
  })
  outputOptions(output, "districts", suspendWhenHidden = FALSE)

  output$select_campus <- renderUI({
    selectizeInput("camp", "Choose a Campus:", choices = c("Choose one   " = "", sort(school_choices())), selected = NULL)
  })
}

我在打印语句中写了查看响应变量何时被触发。我期望应用程序将启动并且反应变量将为 NULL,因为还没有输入,然后当用户做出选择时,uiOutput 将更新。但是发生的事情是,在启动时触发了变量,并且当应该选择 NULL 区域时(或用户选择一次只选择一个),而是打印选择是:

factor(0)
76 Levels: Aldine ISD Alief ISD Alvin ISD Anahuac ISD ... Willis ISD

随后出现此错误:

Warning: Error in Ops.factor: level sets of factors are different
  121: stop
  120: Ops.factor
  117: <reactive:school_choices> [C:\User\Documents\GitHub\project/app.R#822]

我很确定这只是错误,因为当尝试选择多个地区时代码不起作用。

应用程序的其余部分正常运行,除了当用户确实选择了一个地区时,“校园”selectizeInput 不会更新并保持空白。

对于为什么在没有用户输入的情况下触发此变量有什么想法吗?

【问题讨论】:

  • 我尝试了 updateSelectizeInput 而不是 renderUI 建议(这也是我在该项目的先前迭代中所采用的),但它并没有解决问题。我将“school_choices”中的行从choices &lt;- campus_data[(campus_data$DISTNAME == dist$NAME), ] 更改为choices &lt;- campus_data[(campus_data$DISTNAME %in% dist$NAME), ],现在我不再收到错误,但是同样的问题也发生在响应启动时触发并拉出所有区域(而不是等待用户1 个区的输入),并且不会根据用户输入进行更新。

标签: r shiny shinydashboard


【解决方案1】:

您的示例无法重现,因为没有代码可以加载您的数据(可能在 ui 和服务器部分之外)。但是,我认为一个问题是没有更新选择输入对象的代码。 “renderUI”具有通常在满足某些条件时呈现的 ui 元素;您示例中的代码没有附加条件。

试试下面的方法,而不是 renderUI 函数:

    updateSelectInput(session, "camp",
                      choices = schoolchoices(),
                      selected = input$camp)

此外,如果您的地图更新速度仍然过快,请考虑在 school_choices 反应式表达式中使用 isolate() 函数。你甚至可以隔离除操作按钮之外的所有反应。

# From https://shiny.rstudio.com/articles/isolation.html
# The plot render function changes only when the "goButton" button changes, rather than every time the input slider "obs" changes

server <- function(input, output) {
  output$distPlot <- renderPlot({

    # Take a dependency on input$goButton
    input$goButton

    # Use isolate() to avoid dependency on input$obs
    dist <- isolate(rnorm(input$obs))
    hist(dist)
  })
}

【讨论】:

  • 谢谢!我添加了加载数据的代码,以及另一个我忘记的 output,它改变了我的 renderUI 的条件(在我忘记发布之前它就在我的代码中)
  • 关于您的编辑的快速说明:没有库调用(我找不到 useShinyjs()),最后缺少一个右大括号,并且您在问题正文中的网址导航到相同的数据页面。下载的是“Current_Schools”而不是学校或地区 - 对吗?
  • 哦,我似乎找不到 District_options 变量?
  • 糟糕,不确定 URL 是如何弄乱的,但我修复了各区的链接。还添加了库调用。它们并不是全部都需要,我只是不想意外遗漏任何需要的东西。并在末尾添加了缺少的花括号。
  • district_options 也添加了。
猜你喜欢
  • 2015-09-18
  • 2018-03-16
  • 2017-07-30
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 2019-03-27
  • 2020-08-07
  • 1970-01-01
相关资源
最近更新 更多