一、问题
中医证型的关联规则挖掘
背景:
中医药治疗乳腺癌有着广泛的适应证和独特的优势。从整体出发,调整机体气血、阴阳、脏腑功能的平衡,根据不同的临床证候进行辨证论治。确定“先证而治”的方向:即后续证侯尚未出现之前,需要截断恶化病情的哪些后续证侯。找出中医症状间的关联关系和诸多症状间的规律性,并且依据规则分析病因、预测病情发展以及为未来临床诊治提供有效借鉴。能够帮助乳腺癌患者手术后体质的恢复、生存质量的改善,有利于提高患者的生存机率。
目前,中医治疗一般都是采用中医辨证的原则,结合临床医师的从医经验和医学指南进行诊断,然而此方法也存在一定的缺陷。同一种疾病的辨证分型,往往都有不同见解,面对临床症状不典型的患者,初学者很难判断。
因此,找到一种能够根据数据间的关系判断病症的方法显得格外重要。
目的:
- 借助三阴乳腺癌患者的病理信息,找出患者的症状与中医证型之间的关联关系;
- 对截断治疗提供依据,找出潜性证素。
数据概览:
二、为什么选择Apriori算法
Apriori算法,是关联规则最常用也是最经典的挖掘频繁项集的算法,其核心思想是通过连接产生候选项及其支持度然后通过剪枝生成频繁项集。
三、算法原理
算法依据
频繁项集的子集也是频繁项集。(迭代的思想)
名词解释
- 频繁项集:同一属性不同的值
- 支持度计数:不同值的个数
- 支持度:不同值的概率
- 置信度:在A发生的条件下发生B的概率
算法实现步骤
- 确定C1(支持度,一个元素),根据最小支持度进行剪枝,得到L1。
- L1项集随机组合得到元素个数为2的项集,计算C2支持度,根据最小支持度,得到满足条件的L2项集,依次类推,直至所有项集都不满足条件。
- 支持度处理完毕后,对留下来的项集计算置信度。根据置信度公式以及最小置信度进行筛选,最终得到满足条件的项集,即是最终的结果。
算法缺点
Apriori算法的在确定置信度和支持度时需要多次扫面事务数据集,这使得该算法在面对巨大的数据量时,效率降低。
四、问题解决
1、问题分析
本题探究TNM分期与病症之间的关联程度,则以TNM分期和各病症属性为C1项集,剔除小于最小支持度的项集得到L1。以TNM分期为起始点,构建HiXi二项集,计算置信度得到包含Hi的2项集,一次类推,得到最终的项集。再计算置信度,不断剪枝得到符合条件的项集。
2、代码实现
"""
每一行作为一个项集
data概览:A--F都有四种,
目标:确定TNM分期:H1--H4
"""
# 建立项集,读取data文件
# 逐行读取csv文件
import csv
lines = []
with open("中医证型关联规则.csv",'r') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
# print(row)
lines.append(row)
# 执行连接步操作,确定频繁项集
ll_A = {}
ll_H = {}
all_data = []
for i in lines:
all_data.append(i['肝气郁结证型系数'])
all_data.append(i['热毒蕴结证型系数'])
all_data.append(i['冲任失调证型系数'])
all_data.append(i['气血两虚证型系数'])
all_data.append(i['脾胃虚弱证型系数'])
all_data.append(i['肝肾阴虚证型系数'])
all_data.append(i['TNM分期'])
# 计数
for k in range(1,5):
ll_A['A {}'.format(k)] =all_data.count('A {}'.format(k))
ll_A['B {}'.format(k)] = all_data.count('B {}'.format(k))
ll_A['C {}'.format(k)] = all_data.count('C {}'.format(k))
ll_A['D {}'.format(k)] = all_data.count('D {}'.format(k))
ll_A['E {}'.format(k)] = all_data.count('E {}'.format(k))
ll_A['F {}'.format(k)] = all_data.count('F {}'.format(k))
ll_H['H {} '.format(k)] = all_data.count('H {} '.format(k))
print(ll_A)
# 计算支持度
print("支持度大于最小支持度的数据")
all_len = ll_A['A 1'] + ll_A['A 2'] + ll_A['A 3'] + ll_A['A 4']
# print(all_len)
suppot_l = []
nonsupport_l = []
suppot_l_name = []
for j in ll_A.keys():
if ll_A[j]/all_len >= 0.06:
print("{} {}".format(j,ll_A[j]/all_len))
suppot_l.append(ll_A[j]/all_len)
suppot_l_name.append(j)
else:
nonsupport_l.append(j)
print("小于支持度0.06的参数")
print(nonsupport_l)
# 各个证型与H 的关系,构建C2只需考虑两个因素
# H的支持度
print('H的支持度')
for j in ll_H.keys():
print("{} {}".format(j, ll_H[j] / all_len))
print("H与x的支持度")
llc2 = {}
for j in ll_H.keys():
for k in suppot_l_name:
lllo = []
lllo.append(j)
lllo.append(k)
nc1 = k+j
a = 0
for l in lines:
# 判断集合lllo是否为集合l的子集
if set(lllo).issubset(list(l.values())):
a+=1
kk = a/all_len
if kk>0.06:
llc2[nc1] = kk
print(llc2)
print("二项集的长度为{}".format(len(llc2)))
print("构建HXX支持度")
pop = 0
lllc3 = {}
for l in llc2.keys():
for k in suppot_l_name:
llc3 = []
llc3.append(l[0:3])
llc3.append(l[3:]+"")
if k not in llc3:
llc3.append(k)
b = 0
for line in lines:
p = list(line.values())
if set(llc3).issubset(set(p)):
b+=1
dc3 = b/all_len
pop+=b
if dc3>0.06:
lllc3[l+k] = dc3
print(lllc3)
print("三项集的长度为{}".format(len(lllc3)))
print("构建HXXX")
lllc4 = {}
print(lllc3)
for l in lllc3.keys():
for k in suppot_l_name:
llc4 = []
llc4.append(l[0:3])
llc4.append(l[3:7])
llc4.append(l[7:])
if k not in llc4:
llc4.append(k)
c = 0
for line in lines:
p = list(line.values())
if set(llc4).issubset(set(p)):
c+=1
dc4 = c/all_len
if dc4>0.06:
lllc4[l+k] = dc4
print("四项集的长度为{}".format(len(lllc4)))
# 计算置信度
print("计算置信度")
dop = {}
sud = 0
for k in lllc3.keys():
p1 = k[0:3]
p2 = k[7:]
kko = 0
for l in lines:
if p1 in l.values() and p2 in l.values():
kko+=1
lklk = lllc3[k]*all_len/kko
if lklk >0.75:
dop[k] = lklk
print("最终结果")
print(" 病症 TNM分期 支持度 置信度")
# print(dop.keys())
dop.pop('C 3H 4 F 3')
dop.pop('F 3H 4 A 4')
for k in dop.keys():
print(k[0:3]+k[7:]," ",k[3:6]," ",lllc3[k]," ",dop[k])
五、欢迎大家批评指正,莫小凡会持续更新算法知识,大家一起进步呀!