反应性变量在Shiny Dashboard中触发的时间过早(在应用启动时)

时间:2019-03-24 02:51:43

标签: r shiny shinydashboard

我正在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层:学区,邮政编码和县。选择“地区”层后,将弹出条件的“选择”并列出要选择的地区列表。选择一个地区后,将出现另一个条件面板,其中提供了所选地区内的“校园”列表。

要提供“校园” selectizeInput的选项,我有一个school_choices反应变量,该变量拉出与所选地区一起列出的唯一校园名称的列表。

问题似乎出在应用程序启动时,该变量正在触发/触发,而没有任何用户输入该区域。当选择一个地区时,它似乎也没有更新selectizeInput

我尝试将反应变量嵌套在带有if语句的ObserveEvent和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不会更新并且保持空白。

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

1 个答案:

答案 0 :(得分:0)

您的示例不可复制,因为没有代码可加载数据(可能在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)
  })
}