如果想了解列线图制作的原理可以参照已有的文章,推荐的一篇:【肿瘤预测模型系列】Nomogram 绘制原理及R&SAS实现。
总的来说,本文所做的工作是换一个角度来说明列线图的制作原理。之前的有许多的文章来已经说明了这个列线图是如何制作的,以及他这个评分是如何计算出来的,因为静态的列线图不便于实际的使用,通过编程的可以将分值的评分过程进行自动化。经过本人的研究,根据论文所公布的 OR值以及列线图所标注的内容就可以进行列线图分值计算的自动化,从这个过程中,我们也可以了解到列线图制作的一个过程。
提示:以下是本篇文章正文内容,下面案例可供参考
在编程过程中用到了一些变量的名称,为了更地理解编程的过程,现在这里对这些变量的命名的名称做一些解释。
#ls_:列表(list);
#ls_or: OR值列表;
#ls_right_value:列线图中各变量右侧所标注的值;
#ls_left_value:列线图中各变量左侧所标注的值;
#ls_distance:列线图中各变量的取值范围, 即以上两个变量的差值;
#ls_xvar:列线图中各变量的取值。
代码如下,论文给出OR值是更长见:
ls_beta=[np.log(x) for x in ls_or]
ls_beta_abs=[np.abs(x) for x in ls_beta]#进一步取其绝对值
ls_distance_abs=[np.abs(a-b) for a,b in zip(ls_right_value,ls_left_value)]
# 各自标尺的右边数值与左边数值的差,也取其绝对值
ls_pi_pre=[a*b for a,b in zip(ls_beta_abs,ls_distance_abs)]
ls_max_score=[]
for pi_pre in ls_pi_pre:
max_score=np.divide(pi_pre,np.max(ls_pi_pre))*100
ls_max_score.append(max_score)
#从这里可以看到,各个变量的最大得分是成比例的, "最大乘积"人为规定为100分,其它的按照"乘积"与"最大乘积"的比例确定.
# 计算过程是"最大得分"除以"变量取值范围"
ls_unit_score=[a/b for a,b in zip(ls_max_score,ls_distance_abs)]
# 求实际情况下,变量取某个值时,其与"最小取值"的距离(差值)
ls_actual_distance=[a-b for a,b in zip(ls_xvar, ls_left_value)]
ls_actual_distance_abs=map(np.abs,ls_actual_distance)
#单位得分乘以实际的"距离"
ls_score=[a*b for a,b in zip(ls_unit_score,ls_actual_distance_abs)]
total_score=0
for i,val in enumerate(ls_score):
total_score +=ls_score[i]
整理成函数,提供括号内参数即可根据列线图计算出各个变量实际取值的得分和总得分,然后在列线图上查询可以获得事件发生的概率值,代码如下:
def score(ls_right_value,ls_left_value,ls_or,ls_xvar):#提供列线图右边的数值和左边的数值,分类变量为1和0,多分类变量为多个1和0
ls_beta=[np.log(x) for x in ls_or]
ls_beta_abs=[np.abs(x) for x in ls_beta]
ls_distance_abs=[np.abs(a-b) for a,b in zip(ls_right_value,ls_left_value)]# 各自标尺的右边数值与左边数值的差
ls_pi_pre=[a*b for a,b in zip(ls_beta_abs,ls_distance_abs)]
ls_max_score=[]#求各个变量最大的得分
for pi_pre in ls_pi_pre:
max_score=np.divide(pi_pre,np.max(ls_pi_pre))*100
ls_max_score.append(max_score)
ls_unit_score=[a/b for a,b in zip(ls_max_score,ls_distance_abs)]#求各个变量每个刻度单位的得分
ls_actual_distance=[a-b for a,b in zip(ls_xvar, ls_left_value)]#求实际的总得分
ls_actual_distance_abs=map(np.abs,ls_actual_distance)
ls_score=[a*b for a,b in zip(ls_unit_score,ls_actual_distance_abs)]
total_score=0
for i,val in enumerate(ls_score):
total_score +=ls_score[i]
return ls_score,total_score
先提供一张列线图,与上面是同一张。
提供相应的参数:ls_or, ls_right_value, ls_left_value, ls_xvar
if __name__=="__main__":
ls_or=[1.26579,2.50828,0.94866]
ls_score,total_score=logistic.score(ls_right_value=[10,1,10],ls_left_value=[1,0,75],ls_or=ls_or,ls_xvar=[5,1,40])
print(ls_score)
#这里是求肿瘤直径为5,男性,40岁患者的各个变量的评分。
以上过程说明了列线图的特点包括,1.线段的长短是按照“乘积”的比例确定的;2.“最大乘积”的得分人为确定为100分,其它“乘积”的得分按照比例计算。代码和示例都是逻辑回归构建的列线图。列线图中还有一个指标叫做“linear indicator”, 是可选项,其值是“PI-mean(PI)”,PI(prognostic index)是各个变量乘积的和,不包括intercept,“-mean(PI)”是一个"normalization"的数据处理方式,这个琢磨了好一阵子。本人目前致力于临床预测模型的构建和评价,列线图的推广和动态化,欢迎各位同好关注。