ARTICLE · 1200127
药物经济学|不使用VBA在Excel中进行单因素敏感性分析(OWSA)



Include?:取值1/0,输入1表示将该参数纳入OWSA,0则表示不纳入;
LL ID/UL ID:根据Include?的取值,为每个纳入OWSA的参数自动分配唯一的Scenario ID,分别对应下限和上限;下限使用奇数编号,上限使用偶数编号;每个参数的上限ID等于下限ID+1。例如,第一个参数的 LL ID 和 UL ID分别为1和2,第二个参数分别为3和4,以此类推。由以下函数实现:
Active:模型实际调用的参数值,命名对应Name列。根据当前ID,自动选择对应参数的LL、UL或Base。由以下函数实现:
当ID等于LL ID时,Active列代入该参数的下限取值(LL),模型计算结果为该参数取LL时的结果;
当ID等于UL ID时,Active列代入该参数的上限取值(UL),模型计算结果为该参数取UL时的结果;
当ID不等于LL ID或UL ID时,Active列保持该参数的基础值(Base)。

基础结果行(Basecase):引用基础情景下的模型计算结果,包括两组策略比较的增量成本及增量产出,同时作为 Data Table 的输出公式。当ID=0时,所有参数采用基础值;
Scenario ID(AF 列):依次列出所有分析情景的编号。What-If Analysis 将这些编号逐一代入 ID 控制单元格(AG11)。
Incremental Cost(AG、AH 列)与 Incremental Outcome(AI、AJ 列):分别记录各情景下两组策略比较的增量成本和增量产出,用于后续计算 ICER 和 INMB。
选中整个计算区域:AF15:AJ45;



# 注意:Excel公式不支持直接使用注释,复制到Excel前需删除注释。=LET(name,$F$21:$F$35, # 参数名称desc,$E$21:$E$35, # 参数描述idLL,$K$21:$K$35, # 下限Scenario IDidUL,$L$21:$L$35, # 上限Scenario IDscenario,$AF$16:$AF$45, # Scenario IDdc,$AG$16:$AG$45, # 增量成本de,$AI$16:$AI$45, # 增量产出wtp,$W$28, # 支付意愿阈值label,desc&" ("&TEXT($H$21:$H$35,"#,##0.###")&", "&TEXT($I$21:$I$35,"#,##0.###")&")", # 生成参数描述及上下限标签icer,IFERROR(dc/de,NA()), # 计算各情景的ICERinmb,wtp*de-dc, # 计算各情景的INMBllI,XLOOKUP(idLL,scenario,icer), # 匹配下限情景的ICERulI,XLOOKUP(idUL,scenario,icer), # 匹配上限情景的ICERllN,XLOOKUP(idLL,scenario,inmb), # 匹配下限情景的INMBulN,XLOOKUP(idUL,scenario,inmb), # 匹配上限情景的INMBdata,HSTACK(label,llI,ulI,ABS(ulI-llI),llN,ulN,ABS(ulN-llN)), # 合并结果并计算上下限绝对差值result,FILTER(data,($J$21:$J$35=1)*(LEFT(name,2)<>"HC")), # 筛选纳入 OWSA 且属于当前策略比较的参数SORTBY(result,CHOOSECOLS(result,7),-1) # 按 INMB 上下限绝对差值降序排序)
步骤四:可视化
完成OWSA结果整理后,使用Excel图表功能,分别针对Primary Care vs Routine Practice和Hospital Care vs Primary Care的INMB绘制龙卷风图(Tornado Diagram),以直观展示不同参数对成本效果分析结果的影响。


本方法参数表沿用模型的 1. The Parameter Table,包括各参数的 Description、Name、Base、LL、UL 和 Include?。其中,Base、LL 和 UL分别表示参数的基础值、下限和上限,Include?用于控制是否将对应参数纳入 OWSA。该方法无需通过Scenario ID控制参数替换,因此不需要使用LL ID、UL ID 和 Active列。
步骤一:将决策树模型封装为函数
=LAMBDA(p,LET(RPed,INDEX(p,1),PCed,INDEX(p,2),HCed,INDEX(p,3),RPedC,INDEX(p,4),RPldC,INDEX(p,5),PCedC,INDEX(p,6),PCldC,INDEX(p,7),HCedC,INDEX(p,8),HCldC,INDEX(p,9),RPedLE,INDEX(p,10),RPldLE,INDEX(p,11),PCedLE,INDEX(p,12),PCldLE,INDEX(p,13),HCedLE,INDEX(p,14),HCldLE,INDEX(p,15),rpCost,RPed*RPedC+(1-RPed)*RPldC,pcCost,PCed*PCedC+(1-PCed)*PCldC,hcCost,HCed*HCedC+(1-HCed)*HCldC,rpEffect,RPed*RPedLE+(1-RPed)*RPldLE,pcEffect,PCed*PCedLE+(1-PCed)*PCldLE,hcEffect,HCed*HCedLE+(1-HCed)*HCldLE,dcPC,pcCost-rpCost,dcHC,hcCost-pcCost,dePC,pcEffect-rpEffect,deHC,hcEffect-pcEffect,icerPC,IFERROR(dcPC/dePC,NA()),icerHC,IFERROR(dcHC/deHC,NA()),inmbPC,dePC*DSA_DAF!$W$28-dcPC,inmbHC,deHC*DSA_DAF!$W$28-dcHC,VSTACK(HSTACK(rpCost,rpEffect,0,0,0,0),HSTACK(pcCost,pcEffect,dcPC,dePC,icerPC,inmbPC),HSTACK(hcCost,hcEffect,dcHC,deHC,icerHC,inmbHC))))



步骤二:使用动态数组函数实现OWSA
Primary Care vs Routine Practice
在AF10输入以下公式(复制时删去注释):
=LET(names,F$21:F35, # 参数名称desc,E21:E35, # 参数描述base,G21:G35, # 参数基础值low,H21:H35, # 参数下限high,I21:I35, # 参数上限inc,J21:J$35, # 是否纳入 OWSAidx,SEQUENCE(ROWS(base)), # 生成连续参数编号label,desc&" ("&TEXT(low,"#,##0.###")&", "&TEXT(high,"#,##0.###")&")", # 生成包含上下限的参数标签llI,MAP(idx,LAMBDA(i, # 逐一替换参数为下限,计算 ICERINDEX(Tree(IF(idx=i,INDEX(low,i),base)),2,5))),ulI,MAP(idx,LAMBDA(i, # 逐一替换参数为上限,计算 ICERINDEX(Tree(IF(idx=i,INDEX(high,i),base)),2,5))),llN,MAP(idx,LAMBDA(i, # 逐一替换参数为下限,计算 INMBINDEX(Tree(IF(idx=i,INDEX(low,i),base)),2,6))),ulN,MAP(idx,LAMBDA(i, # 逐一替换参数为上限,计算 INMBINDEX(Tree(IF(idx=i,INDEX(high,i),base)),2,6))),data,HSTACK( # 合并 ICER、INMB 及其上下限绝对差值label,llI,ulI,ABS(ulI-llI),llN,ulN,ABS(ulN-llN)),result,FILTER(data,(inc=1)*(LEFT(names,2)<>"HC")), # 筛选纳入 OWSA 的参数,排除 HC 专属参数SORTBY(result,CHOOSECOLS(result,7),-1) # 按 INMB 上下限绝对差值降序排序)
上述公式首先使用 SEQUENCE() 和 ROWS() 根据参数数量自动生成连续编号,随后通过 MAP() 和 LAMBDA() 依次遍历各参数,将当前参数替换为下限或上限,其余参数保持基础值,并将替换后的参数数组传入 Tree() 函数,重新计算对应情景下的决策树模型结果。通过 INDEX() 提取各情景的 ICER 和 INMB,即可完成所有参数的上下限分析。最后,使用 HSTACK() 合并参数名称及计算结果,通过 FILTER() 筛选纳入 OWSA 的参数,再使用 SORTBY() 按照上下限 INMB 的绝对差值降序排列,自动生成 OWSA 结果表。当参数基础值、上下限或纳入范围发生变化时,公式将自动重新计算并更新排序结果。
公式返回7列结果,与原模型的OWSA Results表保持一致:

Hospital Care vs Primary Care
与上一组类似,在AF36输入以下公式:
=LET(names,$F$21:$F$35,desc,$E$21:$E$35,base,$G$21:$G$35,low,$H$21:$H$35,high,$I$21:$I$35,inc,$J$21:$J$35,idx,SEQUENCE(ROWS(base)),label,desc&" ("&TEXT(low,"#,##0.###")&", "&TEXT(high,"#,##0.###")&")",llI,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(low,i),base)),3,5))),ulI,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(high,i),base)),3,5))),llN,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(low,i),base)),3,6))),ulN,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(high,i),base)),3,6))),data,HSTACK(label,llI,ulI,ABS(ulI-llI),llN,ulN,ABS(ulN-llN)),result,FILTER(data,(inc=1)*(LEFT(names,2)<>"RP")),SORTBY(result,CHOOSECOLS(result,7),-1))

=LET(names,$F$21:$F$35,desc,$E$21:$E$35,base,$G$21:$G$35,low,$H$21:$H$35,high,$I$21:$I$35,inc,$J$21:$J$35,idx,SEQUENCE(ROWS(base)),OWSA,LAMBDA(rowNum,exclude,LET(label,desc&" ("&TEXT(low,"#,##0.###")&", "&TEXT(high,"#,##0.###")&")",llI,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(low,i),base)),rowNum,5))),ulI,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(high,i),base)),rowNum,5))),llN,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(low,i),base)),rowNum,6))),ulN,MAP(idx,LAMBDA(i,INDEX(Tree(IF(idx=i,INDEX(high,i),base)),rowNum,6))),results,HSTACK(label,llI,ulI,ABS(ulI-llI),llN,ulN,ABS(ulN-llN)),selected,FILTER(results,(inc=1)*(LEFT(names,2)<>exclude)),SORTBY(selected,CHOOSECOLS(selected,7),-1))),resultBase,Tree(base),resultPC,OWSA(2,"HC"),resultHC,OWSA(3,"RP"),blank4,MAKEARRAY(4,7,LAMBDA(rowNum,colNum,"")),blank2,MAKEARRAY(2,7,LAMBDA(rowNum,colNum,"")),headerBase,HSTACK("Strategy","Expected Cost","Expected Outcome","Incremental Cost","Incremental Outcome","ICER","INMB"),headerOWSA,HSTACK("Parameter","ICER LL","ICER UL","ABS ICER","INMB LL","INMB UL","ABS INMB"),VSTACK(headerBase,HSTACK({"Routine Practice";"Primary Care";"Hospital Care"},resultBase),blank4,HSTACK("Primary Care vs Routine Practice","","","","","",""),headerOWSA,resultPC,blank2,HSTACK("Hospital Care vs Primary Care","","","","","",""),headerOWSA,resultHC))
结果将溢出结果表以及两组排序后的OWSA Results,可在函数中进行参数更新。
















































































