精华 关于“新冠肺炎疫情扩散” 数据分析——图数据模型的讨论
发布于 5 年前 作者 pangguoming 8586 次浏览 最后一次编辑是 4 年前 来自 分享

前述

传染病疫情扩散总体来看是一个带有有限个根节点的树状数据结构,但考虑到人员交叉感染、场所和交通工具的重复使用,传染病疫情扩散又呈现复杂的网状关系,因此考虑采用图数据库作为数据存储、查询、分析工具。 友情链接: GitHub发起援助武汉行动:https://github.com/wuhan2020 患者出行信息:http://hayoou.com/cx/

讨论目的

  1. 旨在创建一个用于针对“传染病疫情扩散” 进行数据精准查询、分析的图数据模型
  2. 数据模型要科学、合理、精准、实用,若数据模型投入到实用中,能成为 传染病网状数据分析的最优解决方案
  3. 因无法获得全部城市的 出行信息 而无法用于 发现密切 接触人员,但是! 可以用于 “流行病学” 分析!关于 流行病学分析 是个医学术语,也就是如果 所有患者都能找到与感染人员的接触关系,说明传染人员都在控制之下,如果发现 有人员“凭空” 感染,没有找到传染关系,说明,存在失控点。如果只导入感染人员的出行信息,就可以分析感染人员之间的相互感染关系,精确发现“凭空” 感染人员,发现失控点。
  4. 通过查询图数据“出度”大的节点,可以定位“疫情爆发场所”和“超级传播者”

前提条件

  1. 暂不考虑数据来源,如:人员信息、场所信息、交通工具信息等,注意:2月4日已经从 Github Wuhan2020小组导入真实数据
  2. 数据模型要能够落实到实际软件工具中使用,目前采用Neo4j作为优先考虑使用的软件工具。
  3. 关于Neo4j 数据库的使用参见:https:// neo4j.com

第一版

最小模型

20200201145104.jpg image.png

说明:

  1. 上图为最小模型,整个图数据模型将有3种节点 和 1中关系组成,(3种节点:人员节点,交通工具节点,场所节点;1种关系:人员与交通工具或场所的关系)
  2. 人员节点带有“INFECTED”标签即为已确诊感染人员
  3. 场所节点要细化,防止成为 超级节点,比如:不能整个北京火车站作为一个节点,应该细化到 火车站每个候车厅、每个候车区域 为一个 场所节点

模型创建语句:

CREATE (PER1:INFECTED {idnum:'370703111111111111', name:'张三', sex:'男',birthday:946656000,home:'山东省潍坊市奎文区',tel:'15000000000'})
CREATE (TRS1:TANSPORT {idnum:'鲁G0001',name:'张三的私家车', type:'PrivateCar'})
CREATE (PLA1:PLACE {name:'张三家',address:'山东省潍坊市潍城区潍坊奎文区健康街108号A802', latlng:'36.1245,21.7895',type:'home'})
CREATE
(PER1)-[:SYAY {beginTime:1579486607,endTime:1579490207,position:'副驾驶座'}]->(TRS1),
(PER1)-[:SYAY {beginTime:1579490307,endTime:1579520207,position:'A3081座'}]->(PLA1)

复杂模型

20200201152212.jpg image.png

说明:

  1. 上图假设PER5位已经感染人员
  2. 围绕人员PER5的场所、交通工具应该由连续的时间轴串起(时间轴即为保存在关系上的beginTime、endTime)
  3. 红色节点即为:INFECTED节点也就是确诊感染人员

模型创建语句:

CREATE (PER1 :PERSON :INFECTED {idnum:'370703111111111111', name:'张三', sex:'男',birthday:946656000,home:'山东省潍坊市奎文区',tel:'15000000000'})
CREATE (PER2 :PERSON :INFECTED {idnum:'370703111111111112', name:'李四', sex:'男',birthday:946657001,home:'山东省潍坊市潍城区',tel:'15000000001'})
CREATE (PER3 :PERSON {idnum:'370703111111111113', name:'王五', sex:'男',birthday:946656002,home:'山东省潍坊市坊子区',tel:'15000000002'})
CREATE (PER4 :PERSON {idnum:'370703111111111114', name:'赵六', sex:'女',birthday:946656003,home:'山东省潍坊市寒亭区',tel:'15000000003'})
CREATE (PER5 :PERSON {idnum:'370703111111111115', name:'王慧', sex:'女',birthday:946656004,home:'山东省潍坊市临朐县',tel:'15000000004'})
CREATE (PER6 :PERSON {idnum:'370703111111111116', name:'李田', sex:'男',birthday:946656005,home:'山东省潍坊市安丘县',tel:'15000000005'})

CREATE (TRS1:TANSPORT {idnum:'鲁G0001',name:'张三的私家车', type:'PrivateCar'})
CREATE (TRS2:TANSPORT {idnum:'鲁G0002',name:'5路', type:'Bus'})
CREATE (TRS3:TANSPORT {idnum:'G-325',name:'青岛-北京', type:'Train'})
CREATE (TRS4:TANSPORT {idnum:'京A0004',name:'北京站-中关村', type:'Bus'})
CREATE (TRS5:TANSPORT {idnum:'海南航空HU7370',name:'潍坊-上海', type:'aircraft'})
CREATE (TRS6:TANSPORT {idnum:'鲁G0003',name:'2路', type:'Bus'})
CREATE (TRS7:TANSPORT {idnum:'鲁G0005',name:'9路', type:'Bus'})

CREATE (PLA1:PLACE {name:'张三家',address:'山东省潍坊市潍城区潍坊奎文区健康街108号A802', latlng:'36.1245,21.7895',type:'home'})
CREATE (PLA2:PLACE {name:'潍坊火车站候车厅',address:'山东省潍坊市潍城区潍坊火车站二楼候车厅', latlng:'36.1245,21.7895',type:'WaitingHall'})
CREATE (PLA3:PLACE {name:'北京火车站出站通道',address:'北京市东城区毛家湾胡同甲13号', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA4:PLACE {name:'北京大学3号宿舍',address:'北京市海淀区颐和园路5号', latlng:'36.1245,21.7895',type:'Dormitory'})
CREATE (PLA5:PLACE {name:'潍坊飞机场候机厅',address:'潍坊市奎文区机场路1号', latlng:'36.1245,21.7895',type:'WaitingHall'})
CREATE (PLA6:PLACE {name:'潍坊飞机场进站通道',address:'潍坊市奎文区机场路1号', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA7:PLACE {name:'上海飞机场出站通道',address:'上海市长宁区虹桥路2550号', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA8:PLACE {name:'李四家',address:'山东省潍坊市潍城区潍坊潍城区福寿街108号A102', latlng:'36.1245,21.7895',type:'home'})
CREATE (PLA9:PLACE {name:'天津火车站出站通道',address:'天津市河北区新纬路1号', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA10:PLACE {name:'王五家',address:'山东省潍坊市潍城区潍坊奎文区幸福路08号A802', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA11:PLACE {name:'紫荆酒店',address:'山东省潍坊市潍城区潍坊高新区幸福路08号A802', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA12:PLACE {name:'德州火车站出站通道',address:'德州市德城区迎宾大街甲1号', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA13:PLACE {name:'王慧家',address:'北京市海淀区万柳中路23号', latlng:'36.1245,21.7895',type:'route'})
CREATE (PLA14:PLACE {name:'李田家',address:'北京市海淀区万柳中路23号', latlng:'36.1245,21.7895',type:'route'})

CREATE //张三出行记录
(PER1)-[:SYAY {beginTime:1579490000,endTime:1579490100,position:''}]->(PLA1),
(PER1)-[:SYAY {beginTime:1579490100,endTime:1579490200,position:'副驾驶座'}]->(TRS1),//从家到私家车
(PER1)-[:GOBY {beginTime:1579490200,endTime:1579490300,position:'步行路线'}]->(PLA2),//从私家车到火车站候车厅
(PER1)-[:SYAY {beginTime:1579490400,endTime:1579490500,position:'6-F2'}]->(TRS3),//从火车站候车厅到火车
(PER1)-[:GOBY {beginTime:1579490600,endTime:1579490700,position:'步行路线'}]->(PLA3),//从火车到出站口
(PER1)-[:SYAY {beginTime:1579490800,endTime:1579490900,position:'3-3'}]->(TRS4),//从出站口到大巴车
(PER1)-[:GOBY {beginTime:1579491000,endTime:1579491100,position:'步行路线'}]->(PLA4)//从大巴车到学校宿舍

CREATE //李四出行记录
(PER2)-[:SYAY {beginTime:1579490000,endTime:1579490100,position:''}]->(PLA8),
(PER2)-[:SYAY {beginTime:1579490100,endTime:1579490200,position:'3-2'}]->(TRS6),//从家到公交
(PER2)-[:GOBY {beginTime:1579490200,endTime:1579490300,position:'步行路线'}]->(PLA2),//从公交到火车站候车厅
(PER2)-[:SYAY {beginTime:1579490400,endTime:1579490500,position:'6-F4'}]->(TRS3),//从火车站候车厅到火车
(PER2)-[:GOBY {beginTime:1579490600,endTime:1579490700,position:'步行路线'}]->(PLA9)//从火车到出站口

CREATE //王五出行记录
(PER3)-[:SYAY {beginTime:1579490000,endTime:1579490100,position:''}]->(PLA10),
(PER3)-[:SYAY {beginTime:1579490100,endTime:1579490200,position:'3-2'}]->(TRS6),//从家到公交
(PER3)-[:GOBY {beginTime:1579490200,endTime:1579490300,position:'步行路线'}]->(PLA11)//从公交到餐馆

CREATE //赵六出行记录
(PER4)-[:SYAY {beginTime:1579490000,endTime:1579490100,position:'6-E1'}]->(TRS3),
(PER4)-[:GOBY {beginTime:1579490600,endTime:1579490700,position:'步行路线'}]->(PLA12)//从火车到出站口

CREATE //王慧出行记录
(PER5)-[:SYAY {beginTime:1579490000,endTime:1579490100,position:'3-2'}]->(TRS4),
(PER5)-[:GOBY {beginTime:1579490600,endTime:1579490700,position:'步行路线'}]->(PLA13)//从大巴到家

CREATE //李田出行记录
(PER6)-[:SYAY {beginTime:1579490000,endTime:1579490100,position:''}]->(PLA14),
(PER6)-[:GOBY {beginTime:1579490600,endTime:1579490700,position:'步行路线'}]->(TRS7),//从家到公交
(PER6)-[:GOBY {beginTime:1579490600,endTime:1579490700,position:'步行路线'}]->(PLA6),
(PER6)-[:SYAY {beginTime:1579490600,endTime:1579490700,position:'B212'}]->(PLA5),
(PER6)-[:SYAY {beginTime:1579490600,endTime:1579490700,position:'A1-1'}]->(TRS5),
(PER6)-[:GOBY {beginTime:1579490600,endTime:1579490700,position:'步行路线'}]->(PLA7)

数据查询

注意:每条人员与场所、交通工具的关系上都带有 起始时间、结束时间 可以按照时间段来查询 1. 查询人员“赵六”是否接触过被感染人员,并列出在何场所、接触了哪些被感染人员

match (n{idnum:'370703111111111114'})-->(m)<--(u:INFECTED) return n,m,u;

image.png image.png

2. 查询人员“王五”是否有“2度”以内直接或间接接触被感染人员并返回图路径

MATCH p=(n {idnum:"370703111111111113"})-[*..2]-(m:INFECTED)
RETURN p

image.png 3. 查询所有感染人员去过的场所和乘坐过的交通工具

MATCH (m:INFECTED)--(n) return n

image.png image.png

4. 查找聚集爆发类传染人员和场所,即可能存在“超级传播者”的场所,这里查找同时出现超过5个感染人员的场所和人员信息,也就是某个场所节点“出度”大于5。

MATCH (k)
WITH k, size((k)--()) as degree
WHERE degree > 5
MATCH (k)--(n)
RETURN n,k,degree;

image.png image.png

2020-02-04更新:

已经从 Github Wuhan2020小组获取到真实数据,现在已经整理成两个csv文件(注意,数据均来自媒体公开,因个人隐私,没有详细姓名等隐私数据): 导入语句: 感染人员交通数据.csv

USING PERIODIC COMMIT 10
LOAD CSV FROM "file:///result.csv" AS line
CREATE(PER1:PERSON :INFECTED :ANONYMOUS {remark:line[6]})
MERGE (TRS1:TANSPORT {idnum:line[5], type:line[4]})
CREATE(PER1)-[:SYAY {beginStation:line[8],endStation:line[9],beginTime:line[2],endTime:line[3],position:line[7],dataSource:line[10],createTime:line[13],updateTime:line[14]}]->(TRS1)
6 回复

自问自答:

1、此数据模型应用范围是多大? 答:可以面向全国疫情发展情况来应用,比如可以将武汉最初几个病例当做图数据的基础节点再网状拓展到全国各个城市。 也可以只面向单个城市,比如我所在的山东省潍坊市目前只发现8个感染人员,此8人可以作为图数据的基础节点。

2、这个数据模型设计的目的是什么? 答:精准 发现 被感染人员的密切接触 人员。

3、那,如果此模型的数据是发现感染者后再通过询问感染者近期出行情况,来创建节点关系数据,能实现以上目的吗? 答:不能,如果是发现感染者后再通过询问感染者近期出行情况,来创建节点关系数据,那么此数据模型将变成一个关于感染人员出行的 “历史记录保存” 载体。此时,此数据模型可以用于 “流行病学” 分析!关于 流行病学分析 是的医学术语,也就是如果 所有患者都有接触关系,说明传染人员都在控制之下,如果发现 有人员“凭空” 感染,没有找到传染关系,说明,存在失控点。如果只导入感染人员的出行信息,就可以分析感染人员之间的相互感染关系,精确发现“凭空” 感染人员,发现失控点。

4、那,如何实现问题2中的目的 答:除非,将整个城市(或国家)的所有人员、交通工具、场所的流动情况全部实时记录进数据模型中(包括历史数据)(比如从铁路、航空、公安 等机构实时获取人员流动数据),然后,从医院确诊的感染者得到出行记录,再去数据模型中查找与此人员 共乘交通工具或者共处一室,或者说是与此人员近距离接触产生1度或2度关系的人员,才能达到问题2中的目的

QQ群网友问答:

问:数据从哪来😭 答:前提条件是,暂不考虑数据来源,我们只做我们能做到的,比什么都不做 强

问:感觉涉及到的个人信息太敏感了,身份证号等。 答:人命比隐私重要

问:测试数据也得有呗,是不是得验证下性能 答:其实可以用爬虫 来爬取 网上公布数据,微博、每个 城市的卫计委 都有些许数据公布,当然这是违法的

后台是否需要对时间进行比较,因为加入G1236动车,我1号乘坐,患病者是10号乘坐,但是这么查询也会查出来我接触过感染人

@LongStockingPipi 嗯,查询语句加上 where 判断时间段是否有交集即可,你可以考虑下怎么写

赞! 增加对时间的过滤/限定可以使分析结果更加有意义。 通过应用相关图算法,能够实现更加复杂的分析:

  • 连通子图/UnionFind:根据关系划分人群
  • 社区检测:模拟可能的传染路径
  • 中心性:定位“超级传播者”

数据来源不是最主要的问题,主要看谁用。数据的治理和隐私保护更加关键。

我已经从 Github Wuhan2020小组导入真实数据,目前因为从关系表导入图数据库很多关系对应不上,导致数据视图看起来很散,但还是能做数据分析的

回到顶部