关于更新应用内

时间:2017-07-19 14:45:37

标签: r leaflet shiny

我正在使用Shiny,我对Leaflet有一个问题。

我想做什么: 我的项目的最终目标是选择特定的法国县。 当选择这些县时,我会在移动中(通过合并)创建形状文件(这是在Leaflet上绘制地图所必需的)和包含所有类型的公共数据的数据库(例如人口数等等)。 ..)仅对应于那些特定的县。

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

详情:实际上,我推出了合并和策划"在另一个.R脚本上,它运行得非常好(我只定义了#34;手动"在启动脚本之前我想绘制的县)。在我的ShinyApp上,这个选择由input$choix_depa变量进行。

现在有点代码。我有三个同时作出反应的脚本: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)中选择一个或多个县的按钮。

在服务器上.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(例如),那么这种变量就像[&#34; 4&#39;,&#34; 87&#34;]。 我的计算机上有95个文件夹(每个县一个)。我使用setwd转到正确的路径,然后contouririsK中加载&#34;形状文件&#34; ,其中K为县的编号。在上一个示例中,我们将contouriris4countouriris87。 这些形状文件合并在contours_IRIS中。 我对数据文件做了同样的事情,我获取了与这些县相关联的数据,我合并了data_BPC 中的所有文件。 (如果我采用前面的示例,我们会在data_BPC4合并data_BPC87data_BPC

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

好的,在我想要在Leaflet地图上绘制这些县的选择后,我必须选择我感兴趣的变量。 这是另一个菜单,我不在这里写所有代码(不是必需的)

observeEvent(input$choix_var_pop, {XXXXXXXXX})

用户想要在地图上绘制的变量的选择位于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文件中调用此输出$ Carte_Pop,以便绘制它。 好的,所有这一切的结果是什么? 正如我之前提到的,当脚本单独使用时,此脚本工作,并且当没有input$choix_depa时(我手动输入要在数组中合并的县,并且它们合并得很好) ,并绘制好地图)。 但当我使用我的3个脚本(global.R,ui.R和server.R)在ShinyApp上时,&#34; new&#34; &#34;地图的价值&#34;没有&#34;保存&#34;

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

但是当我启动ShinyApp时,当我选择我想要的县时(例如13和91),即使contours_IRISdata_BPC很好与对应于13和91的数据合并,因此我认为在map_WGS84内创建的observeEvent(input$choix_depa....) 对应为13和91,当我要求绘图时一个特定的变量(在observeEvent(input$choix_var_pop) 之后绘制的地图不是之前创建的地图,而是旧的MAP&#34; 4和87 (地图是在启动ShinyApp之前在&#34; alone-script&#34; ...上创建。)但我确信100%在observeEvent(input$choix_depa .... )内部创建的MAP是好的。但是,此MAP的&#34;值&#34;不是&#34;由ShinyApp保存&#34; (他们使用MAP的旧值...)。

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

这个问题有点复杂&#34;,如果您有任何疑问,请随时提出!

谢谢! :)

2 个答案:

答案 0 :(得分:3)

  

摘要:如果要使某些输出依赖于其他表达式,则应使用eventReactive,或将该对象存储在reactiveValues中并从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, {
....
每当输入$ choix_depa发生变化时, renderText也会触发,因为它对此有反应。所以不需要把它放在观察者身上。

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中覆盖它。

答案 1 :(得分:0)

感谢Florian的帮助,我将准确描述我的成功:

 output$answ<- renderText({
      paste("Choix départements:", input$choix_depa)
  })

 observeEvent(input$choix_depa, {
      choice=input$choix_depa
  })
  map_reactive <- eventReactive(input$choix_depa,{
     ... merging and creating contours_IRIS (shape file) 
     and data_BPC given input$choix_depa ...

     map_WGS84 = spTransform(
        merge(contours_IRIS, data_BPC, by.x = 'CODE_IRIS', by.y = 'IRIS'),
        CRS("+init=epsg:4326")
        )

     list(map = map_WGS84) 
   })

observeEvent(input$choix_var_pop, {XXXXXXXXX})

... defining variables... 

output$Carte_Pop <- renderLeaflet({
      compulsive = map_reactive()$map
      label = label_reac_pop() 
      var = var_reac_pop() 
      col = col_reac_pop() 
      type = type_reac_pop() 
      unite = unite_reac_pop() 
      values_var = compulsive@data[,var] 

      leaflet(compulsive) %>%

  })

这里“重要”的是在eventReactive末尾添加“list”,以便稍后调用“map_reactive $ map”。 问题解决了 !