R 语言绘制中国地图的最好解决方案!还带九段线小地图!

R 语言绘制中国地图的最好解决方案!还带九段线小地图!

之前的推文中我介绍了使用 Stata 绘制中国地图的终极解决方案,今天给大家带来 R 语言绘制中国地图的终极解决方案!

从知识星球下载附件解压之后你会发现有下面几个文件:

  • china_full_map_long.json:竖版的中国地图(带九段线);
  • centroid_long.csv:竖版的中国地图的省份标签位置数据;
  • china_full_map.json:带九段线小地图的中国地图;
  • centroid.csv:带九段线小地图的中国地图的省份标签位置数据;
  • 省级数据.csv:下面的使用演示中的示例数据,3 月 8 号的新冠肺炎疫情数据。

导入 R 包和示例数据

1
2
3
4
5
6
7
8
9
10
11
12
library(sf)
library(ggplot2)
library(tidyverse)

# 读入数据
da <- read_csv('省级数据.csv') %>%
mutate(
确诊 = cut(确诊,
breaks = c(0.0, 0.99, 9.9, 49.9, 99.9, 999.9, 100000),
labels = c("无", "1~9人", "10~49人", "50~99人", "100~1000人", "> 1000人")
)
)

cut 函数可以用于将连续性变量切割成离散的分组变量。

下面我介绍了两种使用该地图数据的方法:

使用 ggplot2 + sf 绘制地图

这是我一直以来强烈推荐的绘制地图的方法了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 首先读入地图数据,然后把地图数据和示例数据集合并
cnmap <- read_sf('china_full_map.json') %>%
left_join(da, by = c("NAME" = "省份"))

ggplot(cnmap) +
geom_sf(aes(fill = 确诊), color = "gray", size = 0.2) +
theme_ipsum(base_family = cnfont, grid = "") +
worldtilegrid::theme_enhance_wtg() +
theme(legend.position = c(0.2, 0.1),
legend.direction = "horizontal",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
guides(fill = guide_legend(title = "确诊人数",
title.position = "top",
title.hjust = 0.3,
nrow = 3)) +
labs(title = "新冠肺炎确诊病例的省份分布:2020-03-08",
subtitle = "数据来源:JHU CSSE",
caption = "绘制:TidyFriday") +
scale_fill_viridis_d(option = "B", direction = -1) -> p
p

添加省份标签可以直接使用统计变换,但是这个时候直接使用质心位置作为标签位置就不合适了,因为这个地图数据里面的某些省份,例如广东,包括两个部分,主地图的广东和小地图里面的广东,所以这个时候的质心是这两个部分加在一起的质心,所以直接在这个质心上添加的省份标签就会很“不正”。

1
2
3
4
5
6
7
p + 
stat_sf_coordinates(
fun.geometry = function(x) st_centroid(st_zm(x)),
geom = "text", color = "gray99",
mapping = aes(label = NAME), family = cnfont,
size = 4
)

可以看到很多省份的标签都是歪的。如果大家想添加省份标签,可以使用 centroid.csv 数据集:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
centroid <- read_csv("centroid.csv") %>% 
mutate(
NAME = case_when(
NAME == "宁夏" ~ "宁\n夏",
NAME == "陕西" ~ "陕\n西",
NAME == "山西" ~ "山\n西",
NAME == "安徽" ~ "安\n徽",
NAME == "河北" ~ "河\n北",
NAME == "江苏" ~ "江\n苏",
NAME == "江西" ~ "江\n西",
T ~ NAME
)
) %>%
st_as_sf(coords = c("LONG", "LAT"), crs = st_crs(cnmap))

p +
geom_sf_text(data = centroid,
aes(label = NAME, angle = ANGLE,
size = I(SIZE) * 0.6),
family = cnfont, color = "gray99") +
geom_sf_text(data = subset(centroid, NAME == "南海诸岛"),
aes(label = NAME, angle = ANGLE,
size = I(SIZE)),
family = cnfont, color = "gray0")

竖版中国地图可以使用 china_full_map_long.json 数据集绘制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cnmap <- read_sf('china_full_map_long.json') %>% 
left_join(da, by = c("NAME" = "省份"))

ggplot(cnmap) +
geom_sf(aes(fill = 确诊), color = "gray", size = 0.2) +
theme_ipsum(base_family = cnfont, grid = "") +
worldtilegrid::theme_enhance_wtg() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
guides(fill = guide_legend(title = "确诊人数",
title.position = "top",
title.hjust = 0.3,
nrow = 3)) +
labs(title = "新冠肺炎确诊病例的省份分布:2020-03-08",
subtitle = "数据来源:JHU CSSE",
caption = "绘制:TidyFriday") +
scale_fill_viridis_d(option = "B", direction = -1) -> p
p

添加省份标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
centroid_long <- read_csv("centroid_long.csv") %>% 
mutate(
NAME = case_when(
NAME == "宁夏" ~ "宁\n夏",
NAME == "陕西" ~ "陕\n西",
NAME == "山西" ~ "山\n西",
NAME == "安徽" ~ "安\n徽",
NAME == "河北" ~ "河\n北",
NAME == "江苏" ~ "江\n苏",
NAME == "江西" ~ "江\n西",
T ~ NAME
)
) %>%
st_as_sf(coords = c("LONG", "LAT"), crs = st_crs(cnmap))


p +
geom_sf_text(data = centroid_long,
aes(label = NAME, angle = ANGLE,
size = I(SIZE) * 0.6),
family = cnfont, color = "gray99") +
geom_sf_text(data = subset(centroid_long, NAME == "南海诸岛"),
aes(label = NAME, angle = ANGLE,
size = I(SIZE)),
family = cnfont, color = "gray0")

使用 highcharter 绘制中国地图

记得这应该是我第一次介绍 highcharter 的使用,highcharter 包是基于 highcharts JS 图表库封装的,可以用于绘制基于 Web 的交互式图表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
library(highcharter)
da <- read_csv("省级数据.csv") %>%
mutate(确诊 = round(log(确诊), 1))

cnmap <- jsonlite::fromJSON("china_full_map.json",
simplifyVector = FALSE)

highchart(type = "map") %>%
hc_add_series(data = cnmap, type = "mapline",
geojson = TRUE,
color = "gray",
name = "国界线",
showInLegend = FALSE) %>%
hc_add_series_map(map = cnmap,
df = da,
joinBy = c("NAME", "省份"),
value = "确诊",
name = "对数确诊人数:") %>%
hc_title(text = "新冠肺炎确诊人数的省份分布:2020年3月8日") %>%
hc_subtitle(text = "数据来源:<a src='https://github.com/CSSEGISandData/COVID-19'>JHU CSSE</a>") %>%
hc_colorAxis(stops = color_stops()) %>%
hc_add_theme(hc_theme_ft())

竖版地图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cnmap <- jsonlite::fromJSON("china_full_map_long.json", 
simplifyVector = FALSE)

highchart(type = "map") %>%
hc_add_series(data = cnmap, type = "mapline",
geojson = TRUE,
color = "gray",
name = "国界线",
showInLegend = FALSE) %>%
hc_add_series_map(map = cnmap,
df = da,
joinBy = c("NAME", "省份"),
value = "确诊",
name = "对数确诊人数:",
dataLabels = list(enabled = TRUE,
format = '{point.properties.NAME}')) %>%
hc_title(text = "新冠肺炎确诊人数的省份分布:2020年3月8日") %>%
hc_subtitle(text = "数据来源:<a src='https://github.com/CSSEGISandData/COVID-19'>JHU CSSE</a>") %>%
hc_colorAxis(stops = color_stops()) %>%
hc_add_theme(hc_theme_ggplot2())

highcharter 有种自己的一套绘图语言,大家感兴趣的话可以前往 highcharter 的官网学习:http://jkunst.com/highcharter

知识星球附件链接:https://t.zsxq.com/VfQvJUf

#

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×