r - 在应用程序内更新传单 map 的 Shiny (R) 问题

标签 r leaflet shiny

我正在使用 Shiny,但我在使用 Leaflet 时遇到了问题。

我想做什么 :
我的项目的最终目标是选择特定的法国县。
选择这些县后,我会随时(通过合并)创建形状文件(这是在 Leaflet 上绘制 map 所必需的)和包含各种公共(public)数据(例如人口数量等)的数据库。 ..) 只对应于那些特定的县。

我的问题 :我知道在 Shiny App 中“合并”做得很好。但是,我的 Outputmap 不想工作。

详情 :实际上,我在另一个 .R 脚本上启动了我的“合并和绘图”,它运行良好(我只在启动脚本之前“手动”定义了我想要绘制的县)。在我的 ShinyApp 上,这个选择是由 input$choix_depa 选择的。多变的。

现在有一点代码。我有三个同时 react 的脚本: global.R ui.R 和 server.R (这就是 Shiny 的工作原理,你知道)。
对于 global.R(我只在这里展示“interessant”部分)我加载包含所有县数据的数据库文件(不是形状文件!只有数据)

setwd('path')
data_BP = read_delim(
  "database-allFrance.csv",
  ",",
  na = "empty",
  quote = "\"",
  locale = locale(encoding = 'windows-1252')
)

在 ui.R(用户界面)上,我有我的“选择”县:
shinydashboard::tabItem(tabName= "Departements", class = 'active',
           shiny::fluidPage(
           shiny::absolutePanel(
           draggable = FALSE,
           fixed = TRUE, 
           top = 60, left = "auto", right = 20, bottom = "auto",
           width = 330, height = "auto",
           wellPanel(
           shiny::h4("Départements"),
           selectizeInput(inputId = "choix_depa", label = "",multiple=TRUE,
           choices = seq(1,95))
            )
            ), textOutput("answ")
            ),
selectizeInput是允许用户在seq(1,95)中选择一个或多个县的按钮。 .

在 server.R(最重要的)上,我有:
ObserveEvent(input$choix_depa, {
    output$answ<- renderText({
      paste("You choose", input$choix_depa)
    })
    choice=input$choix_depa
    print(choice)
    for (i in input$choix_depa){
      setwd(sprintf("path/county%s",i))

      assign(paste("contouriris",i,sep=""), readOGR(
        dsn = "contours_IRIS_BP.shp",
        layer = "contours_IRIS_BP",
        verbose = FALSE,
        encoding = 'UTF-8'
      ))
      print("modification en cours...")
      assign(paste("data_BP",i,sep=""),subset(data_BP,as.numeric(as.character(data_BP$IRIS))>=as.numeric(i)*10000000&as.numeric(as.character(data_BP$IRIS))<(as.numeric(i)+1)*10000000))

    }

    if (length(input$choix_depa)>=1){
      contours_IRIS  <- get(paste("contouriris",input$choix_depa[1],sep=""))
      data_BPC <- get(paste("data_BP",input$choix_depa[1],sep=""))
    }
    if (length(input$choix_depa)>1){
      for (i in input$choix_depa[-1]){
        contours_IRIS <- rbind(contours_IRIS,get(paste("contouriris",i,sep="")))
        data_BPC <- rbind(data_BPC,get(paste("data_BP",i,sep="")))
      }


    }
    map_WGS84 = spTransform(
      merge(contours_IRIS, data_BPC, by.x = 'CODE_IRIS', by.y = 'IRIS'),
      CRS("+init=epsg:4326")
    ) 
    # Correction of names :
    names(map_WGS84)[names(map_WGS84) == "TYP_IRIS.x"] <- "TYP_IRIS"
  })

您不必了解所有这些代码。
您可以在input$choix_depa中选择县多变的。
如果用户在应用程序内选择了县 4 和县 87,则这种变量类似于 ["4',"87"](例如)。
我的电脑上有 95 个文件夹(每个县一个)。我使用 setwd 去正确的路径,和 我加载“形状文件”contouririsK K 是县的编号。在前面的例子中,我们会有 contouriris4countouriris87 .
这些形状文件合并在 contours_IRIS 中.
我对数据文件做同样的事情,我获取了与这些县和 相关联的数据。我合并了 data_BPC 中的所有文件 . (如果我采用前面的示例,我们会将 data_BPC4data_BPC87 合并到 data_BPC 中)。

在此之后,我使用两个变量( contours_IRISdata_BPC )来创建 map_WGS84变量(我将需要这个变量用于 LeafletOutput)。

好的,在选择了我想在传单 map 上绘制的县之后,我必须选择我感兴趣的变量。
这是另一个菜单,我不在这里写所有代码(不是必需的)
observeEvent(input$choix_var_pop, {XXXXXXXXX})

用户要在 map 上绘制的变量的选择在 input$choix_var_pop 中。 .
在此之后,我创建了在 LeafletMap 上需要的特定变量:
label_reac_pop = reactive({as.character(input$choix_var_pop)})
var_reac_pop = reactive({dico$Variable[dico$Label == label_reac_pop()]})
col_reac_pop = reactive({as.character(dico$Couleur[dico$Label == label_reac_pop()])})
type_reac_pop = reactive({as.character(dico$Type[dico$Label == label_reac_pop()])})
unite_reac_pop = reactive({ifelse(as.character(type_reac_pop()) == "Pct", " %", "")})

最后,我绘制了 LeafletMap:(为了清楚起见,我大大减少了下面的代码)
output$Carte_Pop <- renderLeaflet({

      label = label_reac_pop() 
      var = var_reac_pop() 
      col = col_reac_pop() 
      type = type_reac_pop() 
      unite = unite_reac_pop() 
      values_var = map_WGS84@data[,var] 

      leaflet(map_WGS84) %>%
      addProviderTiles("CartoDB.PositronNoLabels") %>% 
      addProviderTiles("CartoDB.PositronOnlyLabels") %>% 
      setView(lng = 2.468738900000062, lat = 49.19316, zoom = 7)  %>% 
      clearShapes() %>%                       
      clearPopups() %>% 
  })

当然,我在 ui.R 文件中调用这个 output$Carte_Pop 来绘制它。
好吧,这一切的结果是什么?
正如我之前提到的,这个脚本在“单独”时工作,当没有 input$choix_depa 时。 (我手动输入我想在数组中合并的县,它们合并得很好, map 绘制得很好)。
但是当我使用我的 3 个脚本(global.R、ui.R 和 server.R)在 ShinyApp 上时, “ map ”的"new"值未“保存” .

例如:如果我选择(在我的单独脚本上)合并并绘制 4 号和 87 号县,它工作正常 (合并部分和绘图部分运行良好)!

但是 当我启动我的 ShinyApp 时,当我选择我想要的县(例如 13 和 91 )时,即使是 contours_IRISdata_BPC与对应于 13 和 91 的数据很好地合并,所以我假设 map_WGS84这是在 observeEvent(input$choix_depa....) 内部创建的是 对应井到 13 和 91,当我要求绘制特定变量(在 observeEvent(input$choix_var_pop) 之后绘制的 map 不是之前创建的 map ,而是带有 4 和 87 ( map 这是在“单独脚本”上创建的......在启动 ShinyApp 之前!)。但我确信在 observeEvent(input$choix_depa .... ) 内部创建的 MAP 是好的。但是, 的“值(value)”这个 MAP 不是由 ShinyApp “保存”的(他们使用旧的 MAP 值代替......)。

所以我的问题是:我应该怎么做才能绘制新 map (在 APP 内部创建)而不是旧的 BAD ONE(在应用程序之前和外部创建......)?

这个问题有点“复杂”,如果您有任何问题,请随时提问!

谢谢 ! :)

最佳答案

Summary: When you want to make some output dependent on other expressions, you should use an eventReactive, or store the object in an reactiveValues and update that from an observeEvent.



好的,我已经阅读了您的问题,以下是我的想法:
ObserveEvent(input$choix_depa, {
   output$answ<- renderText({
      paste("You choose", input$choix_depa)
    })

这是不好的做法。观察者应该只用于副作用,而不是用于创建输出。那应该变成:
   output$answ<- renderText({
      paste("You choose", input$choix_depa)
    })

ObserveEvent(input$choix_depa, {
....

renderText 也会在 input$choix_depa 更改时触发,因为它对此是 react 性的。所以不需要把它放在观察者中。
map_WGS84 = spTransform(
  merge(contours_IRIS, data_BPC, by.x = 'CODE_IRIS', by.y = 'IRIS'),
  CRS("+init=epsg:4326")
) 

map_WGS84 是一个什么样的对象? 这只有在它是一个reactiveValue 时才有效。 否则,您不会覆盖全局变量,而是覆盖函数observeEvent 中的局部变量。一旦observeEvent 结束,全局map_WGS84 就没有改变。我想这是这里的问题。

最好的选择可能是将其设为 eventReactive ,而不是observeEvent,因为您希望它产生可以在其他地方使用的输出。另一种选择是将 map_WGS84 存储在reactiveValues 表达式中,并从您的observeEvent 中覆盖它。

关于r - 在应用程序内更新传单 map 的 Shiny (R) 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45194038/

相关文章:

javascript - 如何将传单标记固定到数据库中的某个位置?

popup - 将鼠标悬停在 leaflet.js 标记上的弹出窗口上

R Shiny : multiple inputs in reactive{}

r - 如何使用 leaflet.extras addControlGPS 获取 GPS 坐标

r - 如何使用选项列表中的特殊符号作为名称?

r - 使用神经网络包保存神经网络图时遇到问题 - R

c++ - 从 NumericVector 填充 C++ 数组的更好习惯用法

javascript - LeafletJS L.DivIcon HTML 标记文本 - 相对于 map 缩放比例

使用键值数据框替换列值

r - 如何在R中将时间(mm:ss)转换为小数形式