如何使用空间多边形数据框制作反应性闪亮地图 [英] How to make a reactive shiny map with a spatial polygons data frame

查看:41
本文介绍了如何使用空间多边形数据框制作反应性闪亮地图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用空间多边形数据框创建带有 r 的反应式闪亮世界地图.这个想法是有一个不同年份的滑块,可以移动它并用作为国家着色的输入.我的问题是使数据具有反应性,当我运行附加在滑块下方的代码时,会采用输入值(例如,对于所有国家/地区,值为 2004)和错误消息 "Warning in pal(input$year) :一些值超出了色标,将被视为 NA" 弹出.使应用程序静态"(编写 sp_Suicide$2004 而不是 input$year)时,地图会正确显示.如何以访问每个国家/地区的数据而不是简单地将年份作为输入的方式链接滑块的输入?非常感谢您的任何回复!

I want to create a reactive shiny world map with r using a spatial polygons data frame. The idea is to have a slider with different years, which can be moved and is used as an input for coloring the countries. My problem is in making the data reactive, when I run the code that is attached below the slider input values are taken (e.g for all the countries the value is 2004) and the error message "Warning in pal(input$year) : Some values were outside the color scale and will be treated as NA" pops up. When making the application 'static' (writing sp_Suicide$2004 instead of input$year) the map is correctly displayed. How do I link the input of the slider in a way that it accesses the data for each country and does not simply take the year as an input? Thank you very much in advance for any responses!

library(shiny)
library(leaflet)
library(data.table)
library(sp)

#read data in (data table)
Suicide<-fread("Final_Suicide_Data.csv", header=T)

#read shapefile in
world<-readOGR(dsn=".", layer="TM_WORLD_BORDERS-0.3")

#Merge Suicide data to shapefile
sp_Suicide<-sp::merge(world, Suicide, all.x=T, by.x='UN', by.y='un') #SpatialPolygonDataFrame

#make shiny application
ui <- fluidPage(

   # Application title
   titlePanel("Suicide"),

   # Sidebar with a slider input for number of bins 
   sidebarLayout(
     leafletOutput("suicidemap"),
      sidebarPanel(
         sliderInput("year",
                     "Year:",
                     min = 2004,
                     max = 2015,
                     value = 11,
                     sep="")

      )
   )
)



server <- function(input, output, session) {
  output$suicidemap<-renderLeaflet({
    leaflet(data=sp_Suicide)%>%
      addProviderTiles("CartoDB.Positron")%>%
      addPolygons(fillColor=~pal(input$year),
                  fillOpacity = 0.7,
                  color="#BDBDC3",
                  weight=1) %>%
      addLegend("bottomleft",
                pal=pal,
                values=~input$year,
                title="")   

  })
}

# Run the application 
shinyApp(ui = ui, server = server)

更新:非常感谢您的广泛回答:)在下文中,我重新创建了我正在使用的数据外观示例.

UPDATE: Thank you very much for the extensive answer :) In the following I recreated a sample of how the data looks that I'm using.

UN<-c(4,8,12)
Country<-c('Afghanistan', 'Albania', 'Algeria')
`2004`<-c(6.68, 7.69, 4.84)
`2005`<-c(6.68, 7.7, 4.84)
`2006`<-c(6.74, 7.15, 4.56)
`2007`<-c(6.81, 6.61, 4.27)
`2008`<-c(6.87, 6.07, 3.97)
`2009`<-c(6.93, 5.54, 3.69)
`2010`<-c(7, 5, 3.4)
`2011`<-c(7.02, 4.76, 3.34)
`2012`<-c(7.04, 4.52, 3.28)
`2013`<-c(7.06, 4.28, 3.22)
`2014`<-c(7.08, 4.04, 3.16)
`2015`<-c(7.1, 3.8, 3.1)
SuicideData<-data.frame(UN, Country, `2004`, `2005`, `2006`, `2007`, `2008`,    `2009`, `2010`, `2011`, `2012`, `2013`, `2014`, `2015`)
names(SuicideData)<-c("UN", "Country", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015")

此外,这是我(尝试)使用的 shapefile:链接到 shapefile.

Additionally, this is the shapefile that I'm (trying) to use: Link to shapefile.

我试过运行你的代码,但还是不行.我用作输入的数据是否可能必须采用不同的格式?我正在尝试继续使用您将输入数据与 shapefile 合并的有趣方法!

I tried running your code, but it still does not work. Is it possible that the data that I use as an input must be formatted differently? I'm trying to continue with your interesting approach of merging only the input data with the shapefile!

推荐答案

如果没有可重现的示例,很难提供正确的答案.但是,如果我正确理解您要做什么,您似乎错过了几个步骤.我在下面发布了一些示例代码,希望它能作为模板和指南有所帮助.

It is difficult to provide a proper answer without a reproducible example. But, if I understand correctly what you're trying to do, you seem to be missing several steps. I'm posting some sample code below and hopefully it will help as a template and guide.

假设我们有一个按年份 (year) 汇总的年度自杀 (sum_suicides) 数据集 (suidata) 和一个 shapefile (worldshap) 在每个国家/地区都有一个通用标识符(例如ID"),我们可以将其用于合并.解决此问题的一种方法是:

Let's say we have a dataset (suidata) of aggregated yearly suicides (sum_suicides) by year (year) and a shapefile (worldshap) with a common identifier in each of these for country (such as "ID") that we can use for the merge. One way of going about this would then be:

ui <- fluidPage(

  # Application title
  titlePanel("Suicide"),

  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    leafletOutput("suicidemap"),
    sidebarPanel(
      sliderInput("year",
                  "Year:",
                  min = 2004,
                  max = 2015,
                  value = 2011, #value is the starting value so should be value within date range
                  sep="",
                  ticks = FALSE)))) # False for aesthetics because otherwise displays irregular tick intervals

我们首先需要在反应式函数中选择我们想要的数据(基于滑块输入)(注意我们在这个阶段没有合并任何东西,不像上面的例子):

We first need to select the data we want (based on the slider input) in a reactive function (notice we have not merged anything at this stage unlike in your example above):

server <- function(input, output, session) {
selected <- reactive({
suidata <- filter(suidata,
year == input$year)
suidata
})

在这里,我们只是将一个数据子集传递给函数 selected,该子集取决于滑块输入的设置.例如,如果是 2011 年,发送给下面的传单地图的数据将只是 2011 年的数据子集.不过,在此之前,我们要设置底图.这包含我们想要的 Leaflet 地图的所有元素——例如,来自 CartoDB 的图块、指定的长、纬度和缩放(即您必须替换这些值)以及图例.我的假设是抛出的错误是因为您没有正确定义调色板.我的建议是在全局部分设置调色板(即,在闪亮的应用程序之外并在整个数据范围内执行此操作).我在最后给出了一个例子来说明如何做到这一点.

Here, we are just passing to a function selected a subset of data that depends upon what the slider input has been set to. If 2011, for example, the data sent to render the leaflet map below will just be a subset of data for 2011. Before that, though, we want to set a basemap. This contains all the elements of the Leaflet map that we want---e.g., tiles from CartoDB, a specified long, lat, and zoom (i.e. you have to replace these values) as well as a legend. My assumption is that the error thrown up is because you don't define the palette correctly. My advice would be to set the palette in the global section (i.e., outside of the shiny app and do this across the entire range of the data). I give an example at the end for how to do this.

output$suicidemap <- renderLeaflet({
  leaflet() %>% 
    addTiles("CartoDB.Positron") %>% 
    setView(long, lat, zoom= x)%>%
    addLegend("bottomright", pal=pal, values=suidata$sum_suicides, title = "Title of legend")
})

在反应式观察器中,我们然后将 shapefile 与选定的数据合并(注意选定后的重要括号(因为从技术上讲,这是我们正在调用的函数).然后这将调用指定年份的数据并绘制它.

In a a reactive observer we then merge the shapefile with the selected data (note the important brackets after selected (because technically it's a function we're calling). This will then call up the specified year's data and plot it.

observe({
  if(!is.null(input$year)){
      shapefile@data <- left_join(shapefile@data, selected(), by="ID")
      leafletProxy("suicidemap", data = shapefile) %>%
        addTiles() %>% 
        clearShapes() %>% 
        addPolygons(data = shapefile, fillColor = ~pal(sum_suicides), fillOpacity = 0.7, 
                    color = "white", weight = 2)
    }})

}

# Run the application 
shinyApp(ui, server)

定义调色板---假设我们希望地图上的图例显示最高和最低理论值是恒定的,那么我们需要在这个范围内定义一个调色板.如果我们查看年度总量,最高值将是年度自杀人数最多的国家和最低的年度自杀人数最少的国家.因此,我们将全局调色板定义为:

Defining the palette---say we want a legend to be constant on the map displaying the highest and lowest theoretical values then we'd need to define a palette over this range. If we are looking at yearly aggregates, the highest value will be the country with the highest number of yearly suicides and the lowest the country with the lowest number of yearly suicides. Thus, we define our global palette as:

pal <- colorBin("YlOrRd", suidata$sum_suicides, bins=5, na.color = "#bdbdbd")

我希望这有点用:)

这篇关于如何使用空间多边形数据框制作反应性闪亮地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆