用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")
转载自:https://blog.csdn.net/qq_33291559/article/details/79778358