使用R绘制一幅疫情分布图

流行病学中发病情况的地区分布图是很常见的一类做图,R中的ggplot2是一个非常优雅的绘图工具,通过原始的地理测绘数据配合ggplot2绘制地图是比较硬核的一种方法,国家测绘中心早年免费提供地理测绘数据,最近的免费数据是2004年的测绘数据( https://uploads.cosx.org/2009/07/chinaprovinceborderdata_tar_gz.zip )[1],2014年新版的测绘数据则是收费的。两者最直观的区别在于重庆。如果仅是练手可以使用2004年的测绘数据。
流行病学中比较常用的是气泡图,这个在网上已经有很多教程。但用这种方法绘制地图时直接按省份进行染色的教程竟然一篇都没有,摸索了一下,绘制出了相对完美的分布图(发病人数使用的是1月25日的数据):

plot_zoom.png

这个地图的制图难点在于原始的测绘数据虽然是34个省市自治区的(原数据实际没有标出澳门),但因为有的省份面积太大,所以一共花了924个数据用于描述这34个省市自治区,这被称为描述层。为了画出描述层,一共有9万多条几何层的数据,这些几何层的数据是一些坐标点,相互连接起来之后就画出了各省份的边界,而同一组描述层内的几何层数据会拼接成一个省份。
如果是普通的34个数据,那是最容易绘图的了,直接生成34个颜色就可以,但原始的数据是个S4类数据,里面的data子数据包含了924个描述层数据,通过fortify函数解析这个S4数据可以获得9万多条几何层的绘图数据。R自带的plot函数是直接通过描述层调用几何层,因此需要924个颜色去填充,正是通过一篇plot函数绘图的文章让我想到了ggplot2的做图方法[2]。ggplot2中是直接按9万多条原始绘图数据去制图的,所以需要9万多个颜色,我直接套用了原文中生成颜色的函数,做出来的图已经可以用于展示。代码中已添加了详细注释:

# 加载包
library(ggplot2) # 绘图
library(rgdal) # 读取地图数据
library(plyr) # 数据处理
# 全局参数
options(stringsAsFactors = FALSE) # 这个改了省心,r喜欢按因子读取字符
windowsFonts("Times New Roman" = windowsFont("Times New Roman")) # 设置字体
# 读取文件,设置工作路径
setwd("E:/Store/code/03.R/03.ggplot2/06.map/test") # 根据实际情况改自己的工作路径
vData <- readOGR("E:/Store/code/03.R/code/06.maps/map/2014/maps/bou2/bou2_4p.shp") # 按地图文件的实际位置修改
# 数据处理
vTemp <- vData@data;  # S4类数据,用@取子集,得到的为描述层
vDescribeData <- data.frame(vTemp, id = seq(0:924) - 1) # 为描述层添加id,方便后续内联数据
vFormatData <- fortify(vData) # 得倒的为几何层数据
vMapData<-join(vFormatData, vDescribeData, type = "full") # 合并描述层和几何层数据(普通做图这一步并不是必须的,通常只需要几何层就可以做出地图,合并起来更直观一些)
# 读取各省份的发病人数
vNum <- read.csv("num.csv", stringsAsFactors = FALSE)
vProvName <- vNum$vProvName # 省份名称
vNum <- vNum$vNum # 发病人数
vProvCol = vNum # 将发病人数传给颜色,用于表示颜色的深浅

# 颜色函数,从他人博客套用的函数,用处是给每一个描述层生成一个颜色(描述层有924条数据)
fGetColor <- function(mapdata, vProvName, vProvCol, othercol){
  f = function(x, y) ifelse(x %in% y, which(y == x), 0)
  colIndex = sapply(mapdata@data$NAME,  f,  vProvName)
  fg = c(othercol, vProvCol)[colIndex + 1]
  return(fg)
}
# 使用自定义的颜色函数,为描述层生成颜色
vCol <- fGetColor(vData, vProvName, vProvCol, 0)
# 为描述层颜色添加id
vRealCol <- data.frame(vCol, id = seq(0:924) - 1)
# 通过id将描述层的颜色数据和之前的几何层地图数据内联,简单的说就是将924条颜色数据根据id映射到9万多条几何层数据
vMapData <- join(vMapData, vRealCol, type = "full")
# ggplot2常规做图,通过scale_fill_continuous函数产生渐变色
ggplot(vMapData, aes(x = long, y = lat, group = group, fill = as.numeric(vMapData$vCol)))+
  geom_polygon() +
  scale_fill_continuous(low = "white", high = "red") +
  geom_path(colour = "black") +
  ggtitle("新型肺炎确诊病例分布示意图") +
  theme(plot.title = element_text(lineheight = 0.8, face = "bold", size = 20)) +
  theme(axis.text = element_text(size = 15, colour = "black", family = "Times New Roman"),
        axis.title =  element_blank()) +
  # specify tick marks
  coord_map(xlim = c(73, 136), ylim = c(5, 54)) +
  scale_y_continuous(breaks = seq(0, 60, 10)) +
  scale_x_continuous(breaks = seq(70, 135, 10)) +
  # remove guide
  guides(fill = FALSE)

其中num.csv的格式如下:

num.png

下载地址为:http://www.1x1y.top/books/lib/exe/fetch.php?media=num.zip
vNum2列是真实发病人数,我用了渐变色会导致人数较低时偏白色,所以我对发病人数做了一点转换,实际绘图用的是转换后的vNum列数据= =。将发病人数生成新的一列评级数据作为染色标准时做出的图会更好。由于数据转换以及添加地名比较简单,我就没有再接着做了。只要再配合一个爬虫爬取发病人数,就可以实时绘制最新的疫情分布图了。地图文件参考文中给出的链接下载。

参考文献:
[1] 邱怡轩, https://cosx.org/2009/07/drawing-china-map-using-r/.2009.
[2] [阿蛮的杜鹃], https://www.cnblogs.com/lizhilei-123/p/6734378.html.2017.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351