R Shiny:单击多边形时显示图表

Rshiny : displaying chart when clicking on a polygon

我是一个非常渴望学习的 Rshiny 新手,但现在我正面临一个我无法独自克服的问题,如果有人能帮助我,我将不胜感激! :)

我的问题(我猜)很简单:

我用我的多边形创建了一张地图,当我点击它们时我设法显示了一些基本信息 (have a look on here) 但我不知道如何在我的地图下方添加条形图(例如)对于我单击的每个多边形。

有人可以帮我解决这个问题吗? (经过几个小时的尝试,我的眼球真的要从眼眶里蹦出来了!!!)

非常感谢!

罗曼

我的代码:

library(shiny)
library(leaflet)
library(dplyr)
library(magrittr)
library(devtools)
library(RColorBrewer)
library(rgdal)
library(sp)

communes <- readOGR("G:/Ateliers/Projet/communes.shp")
commmunes@data

nom_commune                 INSEE  Variable_1   Variable_2  Variable_3 area_sqkm
1    AUZEVILLE-TOLOSANE     31035         289     8.727212    9.336384  6.979758
2      CASTANET-TOLOSAN     31113          85     4.384877    8.891650  8.460724
3                LABEGE     31254         288     5.047406    2.031651  7.663404
4            PECHBUSQUE     31411         443     6.577743    8.120896  3.099422
5 RAMONVILLE-SAINT-AGNE     31446          95     2.601305    8.909278  6.236784
> 




ui <- fluidPage(
  leafletOutput("mymap"))


  #### SERVEUR R #####


  bins <- c(3,3.5,6,6.5,7,7.5,8,8.5)
  pal <- colorBin("YlOrRd", domain = communes$area_sqkm, bins = bins) 
  labels <- sprintf(
    "<strong>%s</strong><br/>%g km2",
    communes$nom_commun, communes$area_sqkm
  ) %>% lapply(htmltools::HTML)

server <- function(input, output, session) {
  output$mymap<-renderLeaflet(
    leaflet(communes) %>%
      addProviderTiles(providers$Stamen.TonerLite,
                       options = providerTileOptions(noWrap = TRUE)
      ) %>%
      setView(1.50, 43.54, zoom = 12) %>%
      addTiles()  %>% 
      addPolygons(fillColor = ~pal(area_sqkm),
                  weight = 2,
                  opacity = 1,
                  color = "white",
                  dashArray = "3",
                  fillOpacity = 0.7,
                  highlight = highlightOptions(
                    weight = 5,
                    color = "#666",
                    dashArray = "",
                    fillOpacity = 0.7,
                    bringToFront = TRUE),
                  label = labels,
                  labelOptions = labelOptions(
                    style = list("font-weight" = "normal", padding = "3px 8px"),
                    textsize = "15px",
                    direction = "auto")) %>% 
      addLegend(pal = pal, values = ~area_sqkm, opacity = 0.7, title = NULL,
                position = "bottomright")
  )
}     


shinyApp(ui = ui, server=server)

我想在条形图中显示的数据是变量 1,2 和 3 :

data <- read.csv("G:/Ateliers/Projet/communes.csv", sep=";")
data

nom_commune                 INSEE  Variable_1   Variable_2  Variable_3 area_sqkm
1    AUZEVILLE-TOLOSANE     31035         289     8.727212    9.336384  6.979758
2      CASTANET-TOLOSAN     31113          85     4.384877    8.891650  8.460724
3                LABEGE     31254         288     5.047406    2.031651  7.663404
4            PECHBUSQUE     31411         443     6.577743    8.120896  3.099422
5 RAMONVILLE-SAINT-AGNE     31446          95     2.601305    8.909278  6.236784
> 

这是一个包含其他数据的闪亮应用示例,因为我无法访问您的地图形状数据。我相信这可能会完成您需要它做的事情,并且可以根据您的需要进行调整。

我会创建一个 reactiveVal 来存储被单击的多边形区域的 id(此变量存储 input$mymap_shape_click$id)。您在 addPolygons 中使用的数据应该有一个 id 供参考。

在您的图中(或在单独的 reactive 表达式中),您可以根据包含 id.

reactiveVal 过滤数据
library(shiny)
library(leaflet)
library(rgdal)
library(sf)
library(ggplot2)
library(tidyverse)

arcgis_data = st_read("http://data.phl.opendata.arcgis.com/datasets/bc2b2e8e356742568e43b0128c344d03_0.geojson")

arcgis_data$id <- 1:nrow(arcgis_data)  ## Add an 'id' value to each shape

plot_data <- read.table(text =
"id nom_commune                 INSEE  Variable_1   Variable_2  Variable_3 area_sqkm
1    AUZEVILLE-TOLOSANE     31035         289     8.727212    9.336384  6.979758
2      CASTANET-TOLOSAN     31113          85     4.384877    8.891650  8.460724
3                LABEGE     31254         288     5.047406    2.031651  7.663404
4            PECHBUSQUE     31411         443     6.577743    8.120896  3.099422
5 RAMONVILLE-SAINT-AGNE     31446          95     2.601305    8.909278  6.236784", header = T, stringsAsFactors = F
) 

ui <- fluidPage(
  leafletOutput(outputId = "mymap"),
  plotOutput(outputId = "myplot")
)

server <- function(input, output){

  ## use reactive value to store the id from observing the shape click
  rv <- reactiveVal()

  output$mymap <- renderLeaflet({
    leaflet() %>% 
      addPolygons(data = arcgis_data %>% slice(1:5), layerId = ~id) %>% 
      addProviderTiles("CartoDB.Positron")
  })

  observeEvent(input$mymap_shape_click, {
    rv(input$mymap_shape_click$id)
  })

  ## you can now plot your plot based on the id of region selected
  output$myplot <- renderPlot({
    plot_data %>%
      filter(id == rv()) %>%
      pivot_longer(cols = starts_with("Variable"), names_to = "Variable", values_to = "Value") %>%
      ggplot(aes(x = Variable, y = Value)) +
        geom_col()
  })

}

shinyApp(ui, server)

编辑:对于您上传的数据,您不需要为communes添加单独的id。相反,您可以按名称匹配 (nom_commune)。您可以在 layerId 中使用它。这看起来应该有效。我确实删除了一些额外的标签信息,因为我下载的 .shp 文件中似乎缺少这些信息。

library(shiny)
library(leaflet)
library(rgdal)
library(sf)
library(ggplot2)
library(tidyverse)

communes <- readOGR("communes_ok.shp")

ui <- fluidPage(
  leafletOutput(outputId = "mymap"),
  plotOutput(outputId = "myplot")
)

server <- function(input, output){

  ## use reactive values to store the id from observing the shape click
  rv <- reactiveVal()

  output$mymap<-renderLeaflet(
    leaflet(communes) %>%
      addProviderTiles(providers$Stamen.TonerLite,
                       options = providerTileOptions(noWrap = TRUE)) %>%
      setView(1.50, 43.54, zoom = 12) %>%
      addTiles()  %>% 
      addPolygons(fillColor = "blue",
                  weight = 2,
                  opacity = 1,
                  color = "white",
                  dashArray = "3",
                  fillOpacity = 0.3,
                  highlight = highlightOptions(
                    weight = 5,
                    color = "#666",
                    dashArray = "",
                    fillOpacity = 0.7,
                    bringToFront = TRUE),
                  layerId = ~nm_cmmn)
  )

  observeEvent(input$mymap_shape_click, {
    rv(input$mymap_shape_click$id)
  })

  ## you can now 'output' your generated data however you want
  output$myplot <- renderPlot({
    if (is.null(rv())) return (NULL)
    plot_data %>%
      filter(nom_commune == rv()) %>%
      pivot_longer(cols = starts_with("Variable"), names_to = "Variable", values_to = "Value") %>%
      ggplot(aes(x = Variable, y = Value)) +
        geom_col()
  })

}

shinyApp(ui, server)