用迭代算法解决诊疗路径数据汇总

我们要就医院的数据做一个诊疗路径,也就是在某个疾病的治疗周期内或者吃了某个药的后续观察诊疗周期内,所有患者都经历了一个什么样的路径,并且每个路径上的节点都有哪些患者。这个诊疗路径有助于医生了解疾病或者药物的大概率有些路径,对治疗患者有一定的指导作用。

比如,我们对于糖尿病,某个医院的诊疗路径可以说是下图的样子。也就是说患糖尿病的人有395人,但是第一步做检测的人有179,第一步是做手术的有145人,第一步是吃药的有71人。比如做手术1的,全部患者都做检测了,然后第三步人又分流了。医生需要看到的是,针对这个病,有多少个路径,需要用图展示出来。



首先要从数据库中查出来,哪些患者的就诊信息(无论吃药,检测,诊断,手术)是和顶级节点糖尿病有关的。如果说有两个病人的记录是这样的:


那么 6388 的这个人的路径是:第一步是疾病1 (CONDITION_1),第二步是手术2 (PROCEDURE_2),第三步是疾病3 (CONDITION_3)。 6389 的这个人路径是:第一步是手术 1, 第二步是 疾病2 。

所有患者的路径如果和 6388 了一样,就合并,如何和 6389 的一致,另外合并,进行计数。图中的CONCEPT_ID相当于小项,比如吃药,医生会开好几种药,我们需要对每个药也要单独计算多少人服用了。

{[PROCEDURE_1, CONDITION_2, CONDITION_3]={PROCEDURE_1=[1300015304, 1300015444, 1300015811, 1300015301, 1300016147, 1300015497, 1300015444, 1300015938], CONDITION_2=[1300017703, 1300017703, 1300017703, 1300017703, 1300017703, 1300017703], CONDITION_3=[1300017703, 1300017703, 1300017703, 1300017703, 1300017703, 1300017703]}, 
[CONDITION_1, CONDITION_2, CONDITION_3, CONDITION_4]={CONDITION_1=[1300017703, 1300017703], CONDITION_2=[1300017703, 1300017703], CONDITION_3=[1300017703, 1300017703], CONDITION_4=[1300017703]}, 
[CONDITION_1, DRUG_2]={CONDITION_1=[1300017703, 1300017703], DRUG_2=[1119510, 528988, 951511, 1174888, 1163944, 1713332, 923081, 529046, 19049105, 1174888, 1149380, 1137529, 1506270, 923081, 951511, 1119510, 528988, 951511, 1174888, 1163944, 1713332, 923081, 529046, 19049105, 1174888, 1149380, 1137529, 1506270, 923081, 951511]}, 
[CONDITION_1, CONDITION_2]={CONDITION_1=[1300017703, 1300017703], CONDITION_2=[1300017703, 1300017703]}, 
[CONDITION_1, CONDITION_2, CONDITION_3]={CONDITION_1=[1300017703, 1300017703], CONDITION_2=[1300017703, 1300017703], CONDITION_3=[1300017703, 1300017703]}, 
[CONDITION_1, PROCEDURE_2, CONDITION_3]={CONDITION_1=[1300017703, 1300017703], PROCEDURE_2=[1300015811, 1300015811], CONDITION_3=[1300017703, 1300017703]}, 
[CONDITION_1, CONDITION_2, PROCEDURE_3]={CONDITION_1=[1300017703, 1300017703], CONDITION_2=[1300017703, 1300017703], PROCEDURE_3=[1300015811, 1300015811]}, 
[CONDITION_1, PROCEDURE_2, CONDITION_3, PROCEDURE_4]={CONDITION_1=[1300017703, 1300017703], PROCEDURE_2=[1300015810, 1300015810], CONDITION_3=[1300017703, 1300017703], PROCEDURE_4=[1300015810, 1300015810]}, 
[CONDITION_1, PROCEDURE_2, PROCEDURE_3, CONDITION_4]={CONDITION_1=[1300017703, 1300017703], PROCEDURE_2=[1300015311, 1300015311], PROCEDURE_3=[1300015811, 1300015811], CONDITION_4=[1300017703, 1300017703]}, 
[PROCEDURE_1, CONDITION_2, CONDITION_3, PROCEDURE_4]={PROCEDURE_1=[1300015811, 1300015811], CONDITION_2=[1300017703, 1300017703], CONDITION_3=[1300017703, 1300017703], PROCEDURE_4=[1300015811, 1300015811]}, 
[PROCEDURE_1, CONDITION_2, PROCEDURE_3, CONDITION_4]={PROCEDURE_1=[1300015936, 1300016067, 1300015936, 1300016067], CONDITION_2=[1300017703, 1300017703], PROCEDURE_3=[1300015236, 1300015236], CONDITION_4=[1300017703, 1300017703, 1300017703, 1300017703]}, 
[PROCEDURE_1, CONDITION_2, PROCEDURE_3]={PROCEDURE_1=[1300015959, 1300015959], CONDITION_2=[1300017703, 1300017703], PROCEDURE_3=[1300015337, 1300015337]}, 
[PROCEDURE_1, CONDITION_2]={PROCEDURE_1=[1300015811, 1300015811, 1300015811, 1300015811], CONDITION_2=[1300017703, 1300017703]}}

上面的数据结构是所有患者诊疗路径相同的人汇总后的样子,他的java结构是:ConcurrentHashMap<LinkedList<String>, LinkedHashMap<String, List<Integer>>>,外层Map的key是诊疗路径的步骤顺序,value 是另一个Map,它的key 是就诊种类,value则是这个种类下面的小项,也就是 CONCEPT_ID集合。(像上面的CONDITION_1, CONDITION_2的情况是:相同TYPE ,不同的VISIT_OCCURRENCE_ID是不可以汇总在一起的,算是两个步骤的)。

我们还需要将上面的数据结构,转化成java 里面的树形结构,于是定义了下面的TreeNode对象:

// 将相同患者的诊疗路径汇总在一起
		TreeNode treeNode = new TreeNode();
		Map<String, TreeNode> nodeMap = treeNode.getChildren();
		for (LinkedHashMap<String, List<Integer>> itemMap : tempTopMap.values()){
			int level = 1;
			Iterator<String> categoryIterator = itemMap.keySet().iterator();
			buildNode(itemMap, nodeMap, categoryIterator, level);			
		}

针对每一行,我们只需要关注最外层Map 的value,对value 里面的 Map 进行循环。这里我们使用了迭代器,并没有使用 for loop。因为上面数据结构每一行的外层Map的Value相当于一个链表,我们希望将它转变为树形结构的根节点到叶子节点。

// 将相同患者的诊疗路径汇总在一起
TreeNode treeNode = new TreeNode();
Map<String, TreeNode> nodeMap = treeNode.getChildren();
for (LinkedHashMap<String, List<Integer>> itemMap : tempTopMap.values()){
	int level = 1;
	Iterator<String> categoryIterator = itemMap.keySet().iterator();
	buildNode(itemMap, nodeMap, categoryIterator, level);			
}
具体实现:每一个while循环,都是内 Map 里面的迭代,每一个后面的Map数据都是前面的 Children。

private void buildNode(LinkedHashMap<String, List<Integer>> itemMap, 
		Map<String, TreeNode> nodeMap, Iterator<String> categoryIterator, int level) {
	while (categoryIterator.hasNext()){
		String category = categoryIterator.next();
		if (!nodeMap.containsKey(category)){
			nodeMap.put(category, new TreeNode());
		}
		TreeNode aNode = nodeMap.get(category);
		aNode.setCategory(category);;
		aNode.setLevel(level++);
		aNode.getConceptIds().addAll(itemMap.get(category));
		
		buildNode(itemMap, aNode.getChildren(), categoryIterator, level);
	}
}

由于数据结构类似于一个链表,比较适合使用 Iterator 。如果使用 For Loop,可能需要另一种写法。

树形结构TreeNode构成完毕,就可以持久化到数据库了。这个迭代就比较常规化了,因为这次是逐层处理,很方便地对Children进行For 循环:

private void saveClinicalNodes(TreeNode treeNode, Integer parentId){
	// 保存当前节点本身		
	ClinicalPathNode record = new ClinicalPathNode();
	record.setParentId(parentId);
	record.setCohortNumber(treeNode.getCohortNumber());
	record.setConceptId(treeNode.getConceptId());
	record.setNodeText(getNodeText(treeNode));
	record.setNodeType(1); // 普通节点
			
	// 处理非根节点的普通节点层级数字
	if (treeNode.getLevel() != 0){
		String category = treeNode.getCategory();
		String levelStr = category.substring(category.lastIndexOf("_") + 1);
		record.setNodeLevel(Integer.parseInt(levelStr));
	}
	nodeDao.insert(record);
	
	Integer newParentId = record.getId();
	
	// 保存当前节点的叶子属性
	Map<Integer, Integer> conceptIdMap = treeNode.getConceptIdMap();
	if (conceptIdMap.size() > 0){
		for (Integer conceptId : conceptIdMap.keySet()){
			ClinicalPathNode leaf = new ClinicalPathNode();
			leaf.setCohortNumber(conceptIdMap.get(conceptId));
			leaf.setNodeText(getConceptNameById(conceptId));
			leaf.setNodeType(3); // 叶子节点
			leaf.setParentId(newParentId);
			nodeDao.insert(leaf);
		}			
	}
	
	// 递归持久化当前节点的子节点
	Map<String, TreeNode> children = treeNode.getChildren();
	for (String key : children.keySet()){
		saveClinicalNodes(children.get(key), newParentId);
	}
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值