资讯动态

Stata森林图定制全攻略:从metan参数到可发表级图表

发布时间:2026/9/29 2:19:47 来源:尧图企业网站定制
做Meta分析的人十有八九都被那张默认森林图折磨过。metan一跑图是出来了可字号小、配色丑、亚组标题乱成一团放进Word里导出又糊又扁。我有次投稿审稿人专门提了一条意见森林图灰度打印后基本不可读。从那以后我把Stata森林图的个性化定制认真研究了一遍从metan的参数逐项试到gr edit交互调图再到直接用twoway从零重绘踩了不少坑才总结出一套稳定输出方案。这篇文章就讲清楚三件事默认图问题出在哪、每个定制参数到底在改什么、以及从出图到投稿的完整工作流。适合已经能用metan出基础图、想让图表达到可发表水平的读者。1. 默认森林图为什么总被审稿人挑刺1.1 一张合格森林图的信息层级森林图不是简单的散点图它自带一套信息层级。第一层是每个研究单独一行包含研究名称、事件数、样本量以及该研究的效应量和置信区间第二层是固定效应或随机效应的汇总菱形第三层是辅助信息比如权重百分比、掩体线、异质性统计量。这三级信息在视觉上必须有明显区分研究行要能快速扫读汇总菱形要一眼抓住权重和列数据要跟主体错开。默认输出的问题恰恰是层级感太弱。所有文字一个字号方框大小全凭权重自动缩放亚组标题和普通研究行看起来没什么差别审稿人在灰度打印稿上根本分不清哪个是汇总菱形。1.2 先分清哪些不能动、哪些随便动定制之前必须先想清楚统计信息不能乱改装饰信息可以自由发挥。效应量数值、置信区间宽度、权重比例、汇总菱形位置这些是分析结果本身修改它们等同于学术不端。能改的是表达方式字号、颜色、线型、间距、坐标刻度、标签文字、图区比例。我见过有人为了让图好看手动把某个研究的置信区间缩短了这绝对不行。正确做法是所有视觉调整都发生在metan生成图形对象之后而不是改数据。这也是我接下来所有操作的前提。1.3 metan到底生成了什么很多人不知道metan是建立在twoway图形框架之上的。你传给它的graphregion()、plotregion()、title()、xtitle()、xlabel()这些通用图形选项全部有效因为最终渲染出来的确实是一个twoway图。这意味着你对普通twoway图能做的一切调整理论上都能用在森林图上。另外metan跑完会在内存数据集里写入一组下划线开头的变量常见的包括_ES对数尺度效应量、_SE、_LCI/_UCI或_LL/_UL、_WT百分比权重、_USE是否纳入分析。不同版本命名有差异这是后面彻底重绘路线的数据基础先记住有这么回事。2. 核心参数逐个拆解你的图是选项堆出来的2.1 一张能打的森林图我建议这样写先给一个完整的参考命令后面逐个解释关键参数。我用二分类数据的随机效应OR森林图举例* 先统一主题避免每次出图风格漂移 set scheme stcolor * 两臂数据格式试验组事件、对照组事件、试验组总人数、对照组总人数 metan exp_events con_events exp_total con_total, /// or random /// label(namevarstudy) /// lcols(year) /// rcols(exp_events con_events) /// by(region) /// sortby(year) /// xlabel(0.3 0.5 1 2 3, format(%3.1g)) /// xline(1, lpattern(dash) lcolor(gs6)) /// astext(75) /// plotratio(2.2) /// textsize(130) /// boxscale(1.05) /// spacing(1.2) /// xtitle(OR (95% CI)) /// title(各研究及汇总效应) /// graphregion(color(white)) /// plotregion(color(white))这段命令里的核心组合是label(namevarstudy)把研究名变量作为行标签lcols()和rcols()往左右补附加列by(region)做亚组分割sortby(year)控制行顺序。其余的astext、plotratio、textsize、boxscale、spacing是精细美感参数。2.2 lcols/rcols与列布局默认森林图只有研究名、图形区顶多再加一个权重列。但论文里的森林图通常要求呈现事件数、总人数甚至权重百分比。lcols()往左边补列rcols()往右边补列括号里填变量名即可。metan exp_events con_events exp_total con_total, or random /// label(namevarstudy) /// lcols(year) /// rcols(exp_events con_events _WT)这里有个小技巧_WT是metan自动生成的权重百分比变量想在右侧显示权重列先给它设好显示格式再跑图format _WT %4.1f如果你要显示的是未取对数的原始事件数和样本量直接在rcols里放对应变量就行。注意列顺序决定了表格从左到右的内容想好了再排。2.3 图区与文本区的比例plotratio、astext、textsize这三个参数决定了森林图的整体骨架。plotratio(#)控制图形区与文本区的宽度比。默认值记不太清但实际使用中经验法则是这样研究名很长的时候把plotratio调到1.5到2之间给左侧文字留足空间如果图形区太挤置信区间被压成一条短线就上调到2以上。astext(#)更精细它指定文本区域占图形区域的百分比。我一般设75左右意思是在参考线左侧留出足够空间放研究名和左侧列右侧留给x轴刻度方向。如果你发现研究名被截断把astext调大点如果图形区太窄调小点。textsize(#)是整体字号缩放单位是百分比。默认100放到130到140在大部分期刊渲染下比较合适。注意它是整体缩放不能单独调某个文字的大小这一点跟后面的gr edit路线有区别。2.4 方框、菱形与行距boxscale、spacing研究行上的方框大小默认与权重成正比这是Meta分析可视化里很重要的信息编码。但权重差异悬殊时大研究的方框会压住相邻行小研究的方框又小到看不清。boxscale(1.05)在默认基础上微调整体比例即可别动太大。有个常见误用是把boxscale(100)当成统一方框大小来用。确实会让所有方框一样大但同时丢掉了权重这个视觉维度。审稿人如果做过Meta分析一眼就能看出来。真想让权重差异不那么扎眼建议用spacing()把行距拉开而不是抹平方框。spacing(#)控制行与行之间的垂直间距。研究数量多时设1.0到1.1研究少时设1.3到1.5都有不错的效果。设太小会跟汇总菱形贴在一起设太大整张图被拉得又高又空。2.5 坐标轴与参考线xline(1, lpattern(dash) lcolor(gs6))在x1处画一条竖虚线这是森林图的掩体线。OR/RR/HR以1为无效线MD/SMD以0为无效线画的时候别搞错。xlabel()控制x轴刻度。建议刻度覆盖所有研究的置信区间范围不然有些区间伸出图外。用format(%3.1g)把刻度数字格式化避免出现0.300000这类丑陋显示。这里插一句如果你做的是连续性变量MD/SMDmetan的xline参考线要改成xline(0)别跟OR共用一套模板我见过不少人在这翻车。2.6 用表格记下每个参数的作用我把自己常用的参数整理成一个速查表做图时对着填参数作用经验取值or/rr/hr/md/smd效应量类型按分析类型选fixed/random效应模型按异质性决定label(namevar变量)行标签来源研究名变量lcols()/rcols()左右附加列事件数、年份、权重by()亚组分组变量分类变量sortby()研究排序年份/样本量astext(#)文本区宽度%图区70-80plotratio(#)图区/文本区宽度比1.5-2.2textsize(#)整体字号百分比120-140boxscale(#)方框大小缩放1.0-1.2spacing(#)行距1.0-1.3xline()无效线位置OR/RR/HR为1graphregion(color(white))图外背景白色这张表我打印出来贴在显示器边上每次出图之前先对着过一遍基本不会漏参数。3. 亚组分析图的常见需求分组、排序、汇总行Stata如何做亚组分析是搜索量很高的一个词这里单独开一节讲清楚。3.1 亚组分析前先把分组变量收拾干净很多人在by()里直接放一个连续变量或者没有值标签的分组变量结果图上出现一串123456谁也看不懂。正确做法是先给分组变量做好值标签label define regionlab 1 亚洲 2 欧洲 3 北美 label values region regionlabmetan的by()会自动读取值标签作为亚组标题这一步完成之后图上显示的就是亚洲欧洲北美而不是1、2、3。另外一个容易被忽略的点如果分组变量存在缺失值经验做法是先把缺失值单独归为一组未报告而不是让metan把样本丢掉。可以用recode或egen先处理recode region (. 9) label define regionlab 9 未报告, add3.2 by()之后的汇总行与overall取舍by(region)跑完后metan默认每个亚组都会有一个汇总线整体汇总线是否显示取决于你有没有加nooverall。这两个选择在论文里代表不同的分析策略如果你报告的是亚组分析结果而非合并总效应用by(region) nooverall这时候图的焦点在亚组间比较如果既要亚组结果又要整体合并作为参考就保留overall。想改汇总行文字老一点版本直接接字符串新版本用overall的子选项不同版本写法有差异跑之前help metan里搜overall看一眼最稳。3.3 sortby实现顺序即叙事亚组分析的图上行顺序实际上在叙事。你可以让每个亚组内部按年份排序也可以按效应量从大到小排看你想强调什么。sortby(year)按年份排sortby(es)按效应量排多个变量可以并列写。在by()存在时sortby的作用范围是亚组内部也就是每个亚组内分别排序这个特性很适合读图。比如你想让读者一眼看出某个亚组的时间趋势就组内按年份排。3.4 亚组分析时的常见翻车现场我见过最多的翻车是by()分完组图里亚组标题和汇总线全出来了但整体菱形没了。原因是有些metan版本里by()默认隐含nooverall需要显式加overall才能在底部补上整体汇总行。建议每次跑完return list确认一下别等到做图做完才发现。4. 图都画完了还不满意两条微调路线metan参数再怎么调总有些需求满足不了比如某一行想单独换个颜色或者标注某个特殊研究。这时候有两条路线。4.1 交互式微调gr editStata自带图形编辑器graph save先把图存成gph文件然后gr edit打开graph save fig_forest.gph, replace gr edit fig_forest.gph打开编辑器后点选你要改的对象某个方框、某条线、某段文字右键选择编辑就能改颜色、大小、对齐方式。这个方式的优点是没有技术门槛缺点是操作不可复现——下次数据更新重跑图所有手动修改都要重来一遍。所以我的建议是gr edit只用来做一次性最终调整或者在给导师看草稿时快速演示效果。真正的工作流必须写进do文件。4.2 彻底重绘用metan的结果数据自己搭twoway当你需要metan做不出来的版式时就得走重绘路线。原理很简单metan已经把每个研究的效应量、置信区间、权重都算好放在数据里了你把这些数据拿出来用twoway自己画一张森林图。* 跑完 metan 后先看生成了哪些变量 describe _ES _SE _LCI _UCI _WT _USE * 用行号作为y坐标 gen row _n * 置信区间用 rcap研究点用 scatter汇总行用菱形 twoway rcap _LCI _UCI row, horizontal lcolor(gs8) /// || scatter row _ES, msymbol(square) msize(1.6) mcolor(gs4) /// , xline(1, lpattern(dash) lcolor(gs6)) /// ylabel(, noticks labsize(3)) /// xlabel(0.3 0.5 1 2 3, labsize(3)) /// xtitle(OR (95% CI)) /// legend(off) /// graphregion(color(white))想让y轴刻度显示研究名而不是1、2、3用SSC上的labmask命令ssc install labmask labmask row, values(study)然后ylabel里加valuelabel即可。这个方案彻底解放了版式文字想放哪放哪颜色想怎么改怎么改因为你是在直接控制每一个图形对象。4.3 重绘路线的适用场景重绘不是取代metan而是补充。我总结了三类必须重绘的场景一是需要对特定行做突出标记比如把某项关键研究的方框描红二是需要把Meta回归的预测线叠在森林图上三是需要把森林图和其它图表组合成复杂版面。日常出图还是老老实实走metan因为metan自动处理了汇总菱形、异质性统计量、亚组分割这些麻烦事手动画很容易出错。5. 网状Meta分析森林图的定制思路网状meta分析stata是另一个高频搜索词这里单独说说。5.1 network包的基本出图流程网状Meta分析在Stata里主流方案是SSC的network命令包作者是Jeroen Inthout。大致的流程是先安装ssc install network然后根据你的数据结构arm-based还是contrast-based用network setup整理数据指定研究、干预、结局变量最后用network forest出图ssc install network network setup ... // 按你的数据格式组织 network forest OR, fixed effect(OR)不同版本的network包对setup的要求差异挺大装完务必先看help network把示例数据跑通再换自己的数据。5.2 网状森林图和普通森林图的差别网状森林图通常以某一干预为参照展示其它所有干预相对于该参照的效应量所以行数取决于干预数量而不是研究数量。它的定制空间比metan小能用的主要是图形通用选项scheme()、title()、graphregion()、xline()这些。想在网状森林图里做更细致的排版同样可以用4.2节的重绘思路但前提是你的network结果已经写入了数据文件。网状分析还有个常一起出的network league输出的是两两比较的联赛表这个表是文本格式可以复制到Excel里整理后放进论文附录。5.3 森林图排序概率图组合版面网状Meta分析论文里森林图通常不是单独出现的旁边还有排序概率图SUCRA/rank图。用network rank算完排序后你得到的是另一张图。两张图想合成一张用graph combinegraph combine forest.gph rank.gph, cols(2) xcommon /// graphregion(color(white))注意xcommon会让两张图的x轴对齐这在并排比较时非常关键不加的话两图的刻度各自为政读者对比起来很痛苦。6. 导出与投稿别让最后一步毁掉前面的努力6.1 格式怎么选EPS、PDF、TIF、PNG在Stata里graph export的格式选择直接影响期刊接收情况我按投稿场景给个优先级期刊要求矢量图优先导EPS或PDF。EPS基本是Elsevier等出版社的老牌首选。期刊要求位图导TIF300dpi以上。投Word或在线系统导高分辨率PNG600dpi最省事体积可控。graph export fig_forest.eps, replace graph export fig_forest.pdf, replace graph export fig_forest.tif, replace width(3600) height(2700)6.2 多图合并与分辨率设置多图合并时先各自graph save成gph再graph combine最后统一导出graph combine fig1.gph fig2.gph, cols(2) xcommon /// graphregion(color(white)) /// title(组合图标题) graph export fig_combined.tif, replace width(4800) height(3600)分辨率这里有个坑width()和height()设的是像素数dpi是在打印或期刊排版时才换算的。一般期刊要求300dpi纸张宽度按180mm算像素数大概要2126像素以上我习惯设到3600以上保底。6.3 投稿前的检查清单我每次投稿前都过一遍这个清单字体全图字号不小于7pt用Stata默认字体导出中文字符时容易缺字建议图上文字尽量用英文或者提前确认期刊系统支持。颜色把图转成灰度打印一遍确认蓝色方框、红色菱形在灰度下还能区分。参考线xline位置与效应量类型匹配OR/RR/HR在1MD/SMD在0。图注森林图内部不应出现图中无解释的缩写。画布比例图不要太高太瘦建议宽高比2:1左右看起来最舒服。颜色这块多说一句Stata的set printcolor on和set printcolor auto会影响导出图形的色彩处理。如果你的投稿期刊有黑白印刷在线彩图政策建议用printcolor on导一份兼容版本省得编辑来回找你要图。7. 我踩过的坑和现在的固定模板7.1 五个最常踩的坑第一个坑是没做值标签就by()图上全是数字。第二个坑是boxscale(100)让所有方框一样大权重信息视觉上消失审稿人指出后我才彻底改掉。第三个坑是spacing设太小汇总菱形贴住最后一行的置信区间重做了一遍。第四个坑是不同时间做图用了不同scheme导致论文里两张森林图风格完全不同。第五个坑是导出300dpi的PNG后压缩进Word文字糊成一团后来改用600dpi或者直接导EPS才解决。7.2 我的森林图输出模板最后分享我现在固定用的模板直接复制改参数就行* 统一主题与背景 set scheme stcolor, permanently graphregion(color(white)) plotregion(color(white)) * 亚组变量值标签 label define regionlab 1 亚洲 2 欧洲 3 北美, modify label values region regionlab * 出图 metan exp_events con_events exp_total con_total, /// or random /// label(namevarstudy) /// lcols(year) /// rcols(exp_events con_events _WT) /// by(region) /// sortby(year) /// xlabel(0.3 0.5 1 2 3, format(%3.1g)) /// xline(1, lpattern(dash) lcolor(gs6)) /// astext(75) plotratio(2.2) textsize(130) /// boxscale(1.05) spacing(1.2) /// xtitle(OR (95% CI)) /// title(标题) /// graphregion(color(white)) plotregion(color(white)) * 导出 graph export fig_forest.tif, replace width(3600) height(2700)这套模板我从上次投稿用到现在三张森林图一次过审编辑没有再提图片质量问题。最后再分享一个小技巧每做一个项目把当次所有图的导出参数统一记在do文件头部用宏变量存导出路径和分辨率。这样中途改数据重跑所有图能一键重新生成不会出现论文里这张图是旧数据、那张图是新数据的尴尬。森林图定制这件事说到底就是把统计结果用最合适的方式呈现出来别让格式问题拖累工作量已经很大的分析本身。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑