library(sp)
## The legacy packages maptools, rgdal, and rgeos, underpinning the sp package,
## which was just loaded, were retired in October 2023.
## Please refer to R-spatial evolution reports for details, especially
## https://r-spatial.org/r/2023/05/15/evolution4.html.
## It may be desirable to make the sf package available;
## package maintainers should consider adding sf to Suggests:.
library(raster)
library(sf)
## Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
library(ggplot2)
library(gganimate)
##
## 载入程辑包:'gganimate'
## The following object is masked from 'package:raster':
##
## animate
library(RColorBrewer)
library(magick)
## Linking to ImageMagick 6.9.12.93
## Enabled features: cairo, fontconfig, freetype, heic, lcms, pango, raw, rsvg, webp
## Disabled features: fftw, ghostscript, x11
Step1 - 在https://geo.datav.aliyun.com找到上海的地图坐标数据(json格式),然后plot出来,就得到一个上海的空地图
*顺便给大家再提供一个中国地图数据china_map = st_read(dsn = “http://xzqh.mca.gov.cn/data/quanguo_Line.geojson”, stringsAsFactors = FALSE) 是中华人民共和国民政部提供的, GeoJSON 格式的,属于权威数据源,推荐使用
shanghai_map = st_read(dsn = "https://geo.datav.aliyun.com/areas_v2/bound/310000_full.json", stringsAsFactors = FALSE)
## Reading layer `310000_full' from data source
## `https://geo.datav.aliyun.com/areas_v2/bound/310000_full.json'
## using driver `GeoJSON'
## Simple feature collection with 16 features and 9 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 120.8568 ymin: 30.67559 xmax: 122.2471 ymax: 31.87272
## Geodetic CRS: WGS 84
shanghai_map #展示数据格式
## Simple feature collection with 16 features and 9 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 120.8568 ymin: 30.67559 xmax: 122.2471 ymax: 31.87272
## Geodetic CRS: WGS 84
## First 10 features:
## adcode name childrenNum level parent subFeatureIndex
## 1 310101 黄浦区 0 district { "adcode": 310000 } 0
## 2 310104 徐汇区 0 district { "adcode": 310000 } 1
## 3 310105 长宁区 0 district { "adcode": 310000 } 2
## 4 310106 静安区 0 district { "adcode": 310000 } 3
## 5 310107 普陀区 0 district { "adcode": 310000 } 4
## 6 310109 虹口区 0 district { "adcode": 310000 } 5
## 7 310110 杨浦区 0 district { "adcode": 310000 } 6
## 8 310112 闵行区 0 district { "adcode": 310000 } 7
## 9 310113 宝山区 0 district { "adcode": 310000 } 8
## 10 310114 嘉定区 0 district { "adcode": 310000 } 9
## center centroid acroutes
## 1 121.49032, 31.22277 121.48357, 31.21595 100000, 310000
## 2 121.43752, 31.17997 121.43940, 31.16299 100000, 310000
## 3 121.42220, 31.21812 121.38095, 31.20737 100000, 310000
## 4 121.4482, 31.2290 121.45066, 31.27082 100000, 310000
## 5 121.3925, 31.2417 121.39206, 31.25789 100000, 310000
## 6 121.49183, 31.26097 121.48544, 31.27665 100000, 310000
## 7 121.52280, 31.27076 121.52930, 31.29835 100000, 310000
## 8 121.37597, 31.11166 121.41890, 31.08721 100000, 310000
## 9 121.4899, 31.3989 121.40486, 31.39211 100000, 310000
## 10 121.25033, 31.38352 121.24439, 31.35814 100000, 310000
## geometry
## 1 MULTIPOLYGON (((121.476 31....
## 2 MULTIPOLYGON (((121.4577 31...
## 3 MULTIPOLYGON (((121.4395 31...
## 4 MULTIPOLYGON (((121.4577 31...
## 5 MULTIPOLYGON (((121.3542 31...
## 6 MULTIPOLYGON (((121.4854 31...
## 7 MULTIPOLYGON (((121.5165 31...
## 8 MULTIPOLYGON (((121.3587 30...
## 9 MULTIPOLYGON (((121.4253 31...
## 10 MULTIPOLYGON (((121.3365 31...
#plot(shanghai_map)
plot(shanghai_map[1])
Step2 读取疫情数据(各区每日新增阳性患者数)
上海分区<-read.csv('/Users/sanhuai/Desktop/上海分区.csv')
上海分区#看一眼数据格式
## area X2022.4.1 X2022.4.2 X2022.4.3 X2022.4.4 X2022.4.5 X2022.4.6
## 1 徐汇区 639 1042 499 1229 920 1107
## 2 松江区 493 567 263 559 796 7S1
## 3 黄浦区 260 659 824 970 658 1044
## 4 嘉定区 200 617 415 237 481 1408
## 5 虹口区 61 342 188 608 410 668
## 6 杨浦区 134 274 374 220 623 630
## 7 普陀区 245 388 321 254 4S3 1033
## 8 青浦区 87 231 232 314 3S4 470
## 9 静安区 189 324 338 50 302 545
## 10 金山区 49 60 103 52 77 79
## 11 奉贤区 161 157 119 64 144 278
## 12 崇明区 84 113 165 47 79 63
## 13 长宁区 37 100 104 33 84 350
## 14 宝山区 45 485 467 265 554 660
## 15 闵行区 1043 829 940 1381 2937 2409
## 16 浦东新区 2584 2038 3654 7071 8145 8457
## X2022.4.7 X2022.4.8 X2022.4.9 X2022.4.10
## 1 2076 1629 1150 3185
## 2 751 771 500 1825
## 3 1380 2607 548 1761
## 4 933 1505 369 1405
## 5 594 378 349 1238
## 6 601 701 1080 1877
## 7 957 1094 653 1001
## 8 493 342 557 877
## 9 381 665 602 603
## 10 129 90 68 57
## 11 92 97 124 38
## 12 262 170 171 55
## 13 852 614 757 405
## 14 414 2821 2261 1839
## 15 2257 2854 4624 3189
## 16 9050 7286 11130 6732
names(上海分区)[1]<-c('name')
##这个数据的第一列是“area”但是为了和shanghi_map的列名“name”匹配,这里需要修改成“name”
#这里的一个知识点是names()函数可以直接输出表头
Step3 准备等下图片的label要用到的日期数据
##从【上海分区】数据里面可以看到,第一份疫情数据的标题x2022.4.1,R不能把这样格式的数据自动识别为日期数据,使用我们手动来生成日期列表mytime
startTime <- as.Date("2022-4-01",'%Y-%m-%d')
mytime<-startTime+(0:9)
(以”2022-4-01”的徐汇区为例,先画第一张图) Step4 把每日新增病例数分段,以便之后用不同的颜色填充代表新增病例数量/疫情发展的严重程度
上海分区$case = cut(as.numeric(上海分区[1:16,2]),c(1,10,100,200,500,1000,2000,100000),labels=c('<10',"10-100","100-200", "200-500","500-1000","1000-2000",'>2000'))
Step5 合并疫情数据和地图数据
merge_data=merge(shanghai_map,上海分区, by="name", all.x=TRUE)
**提问:为什么要使用merge函数而非直接把疫情数据新增在地图数据之后?
Step6 作图
##先产生一个基本地图
map_base <- ggplot(merge_data) + geom_sf() + xlab("longitude") + ylab("latitude")
map_base
#再在基本地图的基础上
map_full<-map_base + geom_sf(aes(fill = merge_data$case))+scale_fill_brewer(palette = "OrRd",direction = 1)+guides(fill=guide_legend(title = "Number of confirmed cases",reverse = 1))+labs(title = mytime[1])
map_full
## Warning: Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
#存储生成的疫情可视化地图
ggsave(filename = paste(mytime[1],".png",sep=''),plot = map_full,path = "/Users/sanhuai/Desktop",width = 20, height = 20, units = "cm")
## Warning: Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
Step7 循环作图
for (i in (2:11))
#把case数分段
{
上海分区$case = cut(as.numeric(上海分区[1:16,2]),c(1,10,100,200,500,1000,2000,100000),labels=c('<10',"10-100","100-200", "200-500","500-1000","1000-2000",'>2000'))
###画图
map_base <- ggplot(merge_data) + geom_sf() + xlab("经度") + ylab("纬度") ##基本地图
map_full<-map_base + geom_sf(aes(fill = merge_data$case))+scale_fill_brewer(palette = "OrRd",direction = 1)+guides(fill=guide_legend(title = "Number of confirmed cases",reverse = 1))+labs(title = mytime[1])
ggsave(filename = paste(mytime[i-1],".png",sep=''),plot = map_full,path = "/Users/sanhuai/Desktop/maps",width = 20, height = 20, units = "cm")
}
## Warning: Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
## Use of `merge_data$case` is discouraged.
## ℹ Use `case` instead.
Step8 制作动态地图
animate_p=image_animate(image=image_read(path=paste("/Users/sanhuai/Desktop/maps","/",mytime,".png",sep='')))
anim_save(filename = "疫情地图可视化动态图.gif",animation = animate_p,path="/Users/sanhuai/Desktop/maps")