用R–leafletCN包获取各省市地理中心坐标

一、基础介绍

在做地图数据可视化展示时,我们可以选择直接把数据映射到每个省份图形的颜色要素上,leafletCN包提供了非常方便的函数来实现,具体参考Github文档,下面照搬官文的例子做简要说明:

# 加载包
library(leafletCN)
library(leaflet)
library(readr)
library(tidyverse)
library(rgeos) # gCentroid()

# setwd("...")
# 使用Rmarkdown运行脚本时,会显示 Warning message: In strsplit(code, "\n", fixed = TRUE) :
# input string 1 is invalid in this locale--暂时无法解决,不影响使用。
dat <-  data.frame(name = regionNames("china"), # regionNames获取省份名称
                   value = runif(34))
# geojsonMap函数将value映射到省份区域的颜色上
geojsonMap(dat, mapName = "china") 

但是当我们仅想少数几个省份数据时,映射到区域颜色的方式就不这么好看了:

dat2 <- dat[1:5,]
geojsonMap(dat2, mapName = "china") 

此时,将数据可视化在省份区域中心标签上的方式更合理,而加标签的前提是可以准确定位省份级市级区域的中心经纬度坐标,那么如何获取呢?下面就用提取sp对象 + gCentroid()的方式讲解提取过程:

注:sp对象指SpatialPolygonsDataFrame,不了解的可以参考Introduction to visualising spatial data in R

二、获取省份经纬度中心坐标

依据leafletCN-Github文档说明,我们可以按照以下方式获取省级地图的sp对象:

# 省级数据
prov_path <- system.file("geojson/china.json", package = "leafletCN")
# 用read.geoShape()函数将geojson文件读取为SpatialPolygonsDataFrame对象,方便调用
prov_map <- read.geoShape(prov_path)
# 提取其中的描述性数据(要对sp对象有一定了解)
prov_data <- prov_map@data
head(prov_data) 
##   id size             name childNum      cp1     cp2
## 1 65  550 新疆维吾尔自治区       18  84.9023 42.1480
## 2 54  550       西藏自治区        7  87.8695 31.6846
## 3 15  450     内蒙古自治区       12 112.5977 46.3408
## 4 63  800           青海省        8  95.2402 35.4199
## 5 51  900           四川省       21 101.9199 30.1904
## 6 23  700         黑龙江省       13 126.1445 48.7156
str(prov_data) # 验证有34行,与34个省份一致
## 'data.frame':    34 obs. of  6 variables:
##  $ id      : chr  "65" "54" "15" "63" ...
##  $ size    : chr  "550" "550" "450" "800" ...
##  $ name    : chr  "新疆维吾尔自治区" "西藏自治区" "内蒙古自治区" "青海省" ...
##  $ childNum: int  18 7 12 8 21 13 14 16 14 14 ...
##  $ cp1     : num  84.9 87.9 112.6 95.2 101.9 ...
##  $ cp2     : num  42.1 31.7 46.3 35.4 30.2 ...

观察prov_data,其中的cp1和cp2会不会就是省份中心经纬坐标呢?让我们画到地图上验证一下:

leaflet(prov_data) %>% 
    amap() %>% 
    addMarkers(lng = ~cp1, 
               lat = ~cp2, 
               popup = ~name) #点击图标显示名称

观察地图,发现大部分的省份的中心点标记正确的,但是有一些比较离谱,比如内蒙古、澳门和台湾。至此,我们可以有两种方式获取正确的省份地理中心:

方法一:手工调整prov_data中偏差省份的地理中心点——百度内蒙古、澳门和台湾的正确地理位置中心,此方法不做详细说明。

方法二:用rgeos包中的gCentroid()提取每个省份的地理中心点——该方法相对更加严谨,具体如下:

我们先尝试gCentroid()用提取一个省份的地理中心坐标:

# 尝试提取一个省份的sp对象
plot(prov_map[prov_map$name=="内蒙古自治区",]) #内蒙古省份地图

# 获取中心点
prov_center_x <- prov_map[prov_map$name=="内蒙古自治区",] %>% 
    gCentroid() %>% 
    as_tibble()
# 验证:位置正确
leaflet() %>% 
    amap() %>% 
    addMarkers(lng=prov_center_x$x, 
               lat=prov_center_x$y,
               popup = "内蒙古自治区")

# 下一步,循环获取各省中心坐标:
# 首先提取所有省份名称
prov_names <- prov_data$name # 或者regionNames("china")
prov_centroids <- vector("list", length(prov_names))
for (i in seq_along(prov_names)) {
    prov_centroids[[i]] <- prov_map[prov_map$name == prov_names[[i]], ] %>% 
        gCentroid() %>% 
        as_tibble()
}
prov_centroids_tb <- bind_rows(prov_centroids)
prov_centroids_name <- bind_cols(prov_centroids_tb, name = prov_names)
head(prov_centroids_name)
## # A tibble: 6 x 3
##       x     y name            
##   <dbl> <dbl> <chr>           
## 1  85.2  41.1 新疆维吾尔自治区
## 2  88.4  31.5 西藏自治区      
## 3 114.   44.1 内蒙古自治区    
## 4  96.0  35.7 青海省          
## 5 103.   30.6 四川省          
## 6 128.   47.9 黑龙江省
# 将获取的省地理中心标记到地图上进行检验
leaflet(prov_centroids_name) %>% 
    amap() %>% 
    addMarkers(lng = ~x, 
               lat = ~y,
               popup = ~name)

仔细观察发现仅甘肃省和河北省的中心坐标需要微调(原因是这两个省份的形状的确比较特殊),这里我们暂且将甘肃省的中心坐标调整为兰州市中心,将河北省的中心坐标调整为石家庄市中心。这就需要提取城市的中心坐标了,需要用到leafletCN包中的另外一个文件:“geojson/city.json”。

三、提取市级经纬度中心坐标

# 市级数据
city_path <- system.file("geojson/city.json", package = "leafletCN")
city_map <- read.geoShape(city_path)
str(city_map@data) #验证有384行,粗略来讲与全国的城市数目相差不大
## 'data.frame':    384 obs. of  2 variables:
##  $ id  : chr  "1308" "1307" "1306" "1302" ...
##  $ name: chr  "承德" "张家口" "保定" "唐山" ...

# 先尝试获取一个城市的地理中心坐标:
city_map[city_map$name =="承德",] %>% 
    gCentroid()
## SpatialPoints:
##          x        y
## 1 117.5557 41.34672
## Coordinate Reference System (CRS) arguments: NA

# 循环获取所有城市的中心坐标
city_names <- city_map$name
city_centroids <- vector("list", length(city_names))
for (i in seq_along(city_names)){
    city_centroids[[i]] <- city_map[city_map$name == city_names[[i]],] %>% 
        gCentroid() %>% 
        as_tibble()
}

city_centroids_tb <- bind_rows(city_centroids)
city_centroids_name <- bind_cols(city_centroids_tb, name = city_names)
head(city_centroids_name)
## # A tibble: 6 x 3
##       x     y name  
##   <dbl> <dbl> <chr> 
## 1  118.  41.3 承德  
## 2  115.  40.9 张家口
## 3  115.  39.0 保定  
## 4  118.  39.7 唐山  
## 5  117.  38.3 沧州  
## 6  114.  38.1 石家庄

# 选取头几个坐标进行验证:正确
city_centroids_name2 <- head(city_centroids_name)
leaflet(city_centroids_name2) %>% 
    amap() %>% 
    addMarkers(lng = ~x, 
               lat = ~y, 
               popup = ~name)

然后,我们再把甘肃省中心替换为兰州市中心,把河北省中心替换为石家庄市中心。

lz <- city_centroids_name %>% 
    filter(name == "兰州")
sjz <- city_centroids_name %>% 
    filter(name == "石家庄") 

prov_centroids_name[prov_centroids_name$name=="河北省",][,1:2] <- sjz[,1:2]
prov_centroids_name[prov_centroids_name$name=="甘肃省",][,1:2] <- lz[,1:2]

# 再次验省份中心坐标的准确性:所有省份都基本正确
leaflet(prov_centroids_name) %>% 
    amap() %>% 
    addMarkers(lng = ~x, 
               lat = ~y,
               popup = ~name)

这次想要仅展示少数几个省份的数据就好看多了(沿用最开始的dat2数据):

dat2_centroids <- dat2 %>% 
    mutate(name = parse_character(name)) %>% # 将factor转换为character,避免warning
    left_join(prov_centroids_name, by = "name")
popup_text <- paste0(dat2_centroids$name, ":", round(dat2_centroids$value, 3))

# 简洁明了的地图:
leaflet(dat2_centroids) %>% 
    amap() %>% 
    addMarkers(lng = ~x, 
               lat = ~y,
               popup = popup_text) #点击图标显示数据

最后,将省份中心与市中心经纬坐标数据保存为CSV或RDS文件备用:

write.csv(prov_centroids_name, "data/prov_centroids.csv")
write.csv(city_centroids_name, "data/city_centroids.csv")

下载:各省市中心经纬坐标数据CSV文件

转载自:https://blog.csdn.net/qq_33291559/article/details/79778358

You may also like...