一次不太成功的搬砖(中):rvest爬取法定传染病疫情月报数据
文章目录
数据提取
现在,可以着手把存储在附件里的信息结构化提取出来了。但在这之前,还有一个硬骨头要啃。
要把图片附件识别成文本。
首先考虑OCR。但是Abbyy Finereader似乎没有Ubuntu版本。其他一些主流工具要钱。网上找到几个免费OCR工具,试用了下,转出来一堆乱码亲妈都唔识得。一怒之下,放了个大招:
手工录入。
这项工作很不好做,让我不禁怀疑起人生。但只有经过这样的磨练,才能对疾控系统的信息化水平有一个实操层面的认识。倘若遇到这方面的项目机会,记得要把工程预算乘以3。
图片方面的坑包括:
- 有些图片附件分辨率低到了厚马赛克水准,别说OCR,钛金狗眼也认不出
- 有些表格作为OLE对象内嵌到了Word文件里,当我满怀希望点进去才发现,这个内嵌对象竟仍是个图片
- 有个别文件特别贴心地把表格割成两张图,插到了正文里
满脸辛酸地处理完了这些杂碎,把doc和xls存作docx和xlsx,接下来总算能把它们当成正常的xml来处理了。
资料
有读者留言提到,这些数据其实都可以从公共卫生信息网申请到。没错。但是作为数据公开党,我对这种公共数据管制甚至收费牟利的做法非常不屑。这根本不符合如今的时代精神。本文提到的这些结构化数据文档,都已打包存到七牛云。人人都可以免费用。
docxtractr
docx和xlsx本质上是一堆xml文件打包到zip里。所以2007以后的MS Office文件都更好处理,解包后按xml语法抽节点信息就是。不过人上有人,懒外有懒。我是不会用XML包做通用解的,敲那么多代码手指不会痛吗?
除非人命关天,否则莫造新轮。
我们可用docxtractr
处理docx,readxl
处理xlsx,readr
处理csv。docxtractr
有个特别贴心的函数docx_extract_tbl
,直接把word正文里的表格提取成data.frame,就跟html_table
一样。
提取工具函数
通过前面的苦力活,现在只剩下三种文件形态:csv、xlsx、docx。写一个通用方法来分类提取。
|
|
然后用lapply
跑个隐式循环,就把所有表格都以data.frame的形式提出来了,存为一个逼格李斯特(big list)。
|
|
数据清理
这样得到的数据虽然结构化了,但仍有很多问题。
- 变量名都是X1, X2, …, 需要转成数据原本的表头
- 存在空行和空列
- 数值列含有缺失值和数值文本混合值
- 病名多样,比如“甲肝”和“甲型肝炎”本质上是一回事
可以分几步走:重新定义表头,然后舍弃/纠正不规范数值,最后归并同类病名。
值规范化
构造两个工作函数,然后lapply一轮就能把数值规范化:
redefCol
用来规范每张表格的表头。如当前用的是X1, X2, …,就用首行替代。最后把变量名中的空格、星号都去掉cleanTbl
用来去掉空列、空行,去掉“病名”列中的空格、星号、括号等,把发病数、死亡数两列的非数字字符都去掉
提示
由于后面要用到并行计算,所以工作函数内要么显式引用加载包stringr
等,要么在函数前声明其所在命名空间,如stringr::str_detect()
。
|
|
cleanTbl
函数内部用了好几个apply家族函数,可想而知肯定很慢。所以遍历data列表时,可以用一下并行计算parallel
。
先要创建一个集群,利用makeCluster
。这里声明构造4个集群,因为detectCores()
会告诉系统,这台电脑有4核。少声明几个也无所谓。
|
|
创建集群,就是为了用parLapply
,这其实就是lapply
的并行版本。原来是snow
包里的。并行调用cleanTbl
后,清干净的列表存为dat。尺寸上明显小了很多。
|
|
dat用日期命名,然后再用一次lapply隐式循环,遍历dat的同时为每张表新增一列DOP。这里要用超赋值符«-。
|
|
清理完毕!最后调用dplyr
的bind_rows
,把这些列表中包裹的数据框提出来合并成一个大数据框。这个框就是后续分析的基础了。
|
|
归并同类
首先,定义一个正则转化字典,然后遍历一遍,就把同类病名都归并了。
|
|
再然后,创建一个变量Class,标记甲、乙、丙三个分类。
|
|
通用作图函数
接下来我计划做一系列面积图,简单看看疫情的时间分布有什么有趣之处。但每次整形一遍,再写一堆ggplot命令是很烦人的。我盘算了下,大约要跑十几张图,如果写个通用作图函数增加代码复用性,整体来说还是合算的。
作为码农,不光要坚定地偷懒,还要偷得值。
简单说来,这个函数可以接过一个初步分析结果数据框,根据指定的xvar、yvar、gvar来设置geom_area()
的aes
参数,再套用一下HighChart的主题。这样每次做图,只需要写一行代码就完事了。
下面的代码是本次分析可视化的最核心部分。
|
|
利用这个函数,只要来个数据框,就能出图。此外也不失灵活性,部分美学效果可以自定义调整。