1、背景与数据来源介绍java
新型肺炎做为一种存在潜伏期的传染病,分析其传染关系及接触关系很是有利于疫情的防控,对疫后的研究分析也有帮助。本文将介绍基于图数据库对新型肺炎图谱进行建模与分析的过程及效果。数据库
图数据库(Graph Database)是一种复杂关系数据的处理系统,一种使用顶点、边和属性来表示与存储数据,并以图结构进行语义查询的数据库。图数据库的关键概念是边,经过边将顶点链接在一块儿,从而进行快速的图检索操做。ide
图数据库很是适合用于分析此类关联关系数据,这次使用百度开源的HugeGraph图数据库做为分析工具。分析数据数据均来源于各地卫健委或权威网站公开公布,如北京、石家庄、温州、南昌、宜春等城市。分析场景包括:工具
新型肺炎传染图谱网站
本次演示共导入了5类实体数据:包括正常人、病例、地址、交通工具、医院等数据信息,以及各种实体之间的关联关系,如“病例乘坐某交通工具”关系。spa
数据导入后效果3d
导入数据详细介绍以下:code
一、病例数据:共导入了43条病例数据,包括病例的年龄、性别、感染缘由、症状、确诊日期、省市等信息。blog
二、地址数据:共导入了32条地址数据,好比“裕华区裕翔社区卫生服务中心”,主要包括上述病例出现过的地址。rem
三、交通工具数据:共导入了6条交通工具数据,如高铁、航班、公交地铁等信息,主要包括上述病例乘坐过的交通工具。(这个数据较少省市公布)
四、医院数据:共导入了10条医院数据,如“北医科大学第四医院”,主要包括上述病例收治的医院。
五、“传染链”视图:共导入了8条传染数据,如“病例甲传染了病例乙”,主要包括上述病例和疑似病例的传染关系。
六、“交通工具链”视图:共导入了8条交通工具乘坐信息数据,好比“病例甲在1月18日乘坐了G310次高铁”,主要包括上述病例和疑似病例的乘坐关系。
七、“出现于场所”视图:共导入了9条病例、19条正常人出现的场所地址信息数据,好比“病例甲在1月21日10点到过XX超市”,主要包括上述病例和正常人的出现的地址关系。
八、某个病例关系链视图:除上述关联关系外,还导入了“感染于”、“现住”、“常住”、“收治于”等关系,主要包括上述病例和疑似病例的各类其它关系。
九、“正常人”数据:共导入了22条正常人数据,包括姓名、年龄、性别、详细地址等信息;另外还导入了28条正常人的轨迹信息,如“某个正常人在1月19日乘坐过G512次高铁”、“某个正常人在1月20日10点到过XX超市”。(注意:正常人数据并不许确,仅供演示参考)
到此,数据建模与导入介绍完毕。接下来基于此数据集进行各类分析场景的演示。
2、分析场景演示
场景1:基本统计信息
本场景中包含了7种基本的统计分析,分别是:分析确诊病例的城市分布状况、病例的省份分布状况、病例的确诊日期分布状况、病例的平均年龄、病例的年龄段分布状况等。(注意:这些统计信息仅仅是基于上述导入数据集计算的)
场景2:与确诊病例直接接触过的人(1层关系)
下图中的3个红色点表明已确诊病例,深蓝色点表明正常人,这些人与病例有过接触,有感染风险:
查询语句:
g.V().hasLabel('病例') .union(out('乘坐').in('正常乘坐').simplePath(), out('出现于').in('正常出现于').simplePath()) .hasLabel('正常人').path()
注:查询语句使用的是HugeGraph提供的标准Gremlin图查询语言,下同。
场景3:与确诊病例间接接触过的人(2层关系)
下图中的左上角红色点表明已确诊病例,深蓝色点表明正常人,这些正常人与病例有过直接接触(如田某某),或者间接接触(其它蓝色点,如李某某与田某某在建设大街XX烟酒超市接触过),均有感染风险:
查询语句:
g.V().hasLabel('病例') .union( out('乘坐').in('正常乘坐').simplePath().out('正常乘坐').in('正常乘坐').simplePath(), out('出现于').in('正常出现于').simplePath().out('正常出现于').in('正常出现于').simplePath()) .hasLabel('正常人').path()
场景4:某个正常人是否与确诊病例直接或间接接触过
换一个角度,以正常人为中心来考虑并进行分析。下图中的左上角蓝色点是一个正常人“黄某某”,查看他是否有直接或间接和红色点所表明的已确诊病例关系,从图中能够看出,他与病例“sjz0203-21”有直接接触,且与病例“sjz0202-14”有间接接触。
查询语句:
g.V('黄某某').repeat(out('正常乘坐','正常出现于') .in('正常乘坐','正常出现于','乘坐','出现于').simplePath()) .times(2).emit(hasLabel('病例')) .hasLabel('病例').path()
场景5:找出全部的超级传播者
咱们要从全部的病例里面找到超级传播者,这里假设一个病例若传染了5个以上的人则定义为超级传播者,下图中心的红色点“sjz0202-14”病例便是找出来的超级传播者(传染了“sjz0202-15”和“sjz0203-21”等5我的)。
查询语句:
g.V().hasLabel('病例').where(outE('传染').count().is(gte(5))) .order().by(outE('传染').count(),desc).limit(10)
场景6:找出超级传播者接触过的人(包括已确诊病例和正常人)
通常来讲,超级传播者的风险比较高,与超级传播者接触过的人风险也是比较高的,下图展现了如何找到这些高风险的人:中心的红色点是超级传播者,周围的红色点和蓝色点所表明的人是高风险的人。
查询语句:
g.V().hasLabel('病例').where(outE('传染').count().is(gte(5))) .order().by(outE('传染').count(),desc).limit(10) .both().choose(hasLabel('病例'),identity(), both('乘坐','出现于','正常乘坐','正常出现于').simplePath()) .path()
场景7:病例传染链分析(如疫情后病毒变异分析)
为了在疫情后进行病毒变异分析,须要分析一个病例的上游传染链,即某病例是被谁传染的,上一我的又是被谁传染的,找到直到源头,造成一条传染链。有了传染链以后能够对链上的每一个病例的病毒信息进行比对分析(假设每条病例数据里面存储了病毒的身份签名信息)。下图展现了最左边的病例“sjz0205-123”的传染链,传染源头则是最右边的病例“sjz0127-9”。
查询语句:
g.V('sjz0205-123').repeat(__.in('传染')) .until(__.not(__.in('传染'))).path()
下一步计算链上的病毒变异次数,也就是比对链上病例的病毒签名,计算去重以后病毒的种类数量。以下图示例中的结果是变异3次。
查询语句:
g.V('sjz0205-123').repeat(__.in('传染')) .until(__.not(__.in('传染'))).path() .unfold().values('病毒').dedup().count()
每一个病例都有一条传染链,为了分析全部病例的传染链的病毒变异状况,好比找出变异次数最多的那条链,那么须要先找到全部的传染链,而后计算每条链的变异次数,最后比较各条链,找出变异次数最多的一条链。下图展现了全部的传染链。
查询语句:
g.V().hasLabel('病例').repeat(__.in('传染')) .until(__.not(__.in('传染'))).path().dedup()
下图展现了全部传染链的病毒变异次数。
查询语句:
g.V().hasLabel('病例').repeat(__.in('传染')).until(__.not(__.in('传染'))).path().dedup() .project('传染链','变异次数').by(unfold().id().fold()).by(unfold().values('病毒').dedup().count())
场景8:病例传染环分析
在疫情早中期,对于某个病例来讲,随着病毒传染更多的人,每每会在该病例的周围造成一圈一圈的传染环,好比某病例传染了3我的,假设被传染的人又每一个传染3人,则第一层环上包括3人,第二层环上包含9人。为了分析某一层环上病例的病毒变异状况,须要找到该层环上的病例,而后对环上的每一个病例的病毒信息进行比对分析。下图展现了病例“sjz0127-9”的第一层和第二层传染环。
查询语句:
g.V('sjz0127-9').repeat(out('传染')).times(2).emit().path()
更多场景或者任何问题请反馈至邮箱:javaloveme@gmail.com