深入源码解决问题!Stata 绘制漏斗图时如何设置散点颜色

教育   2024-11-26 12:42   安徽  


最近有个小伙伴遇到了这样的一个问题,她在使用 Stata 绘制漏斗图时想要设置散点的颜色却不知如何设置。今天我们就一起看一下这个问题。

由于我对 Meta 分析也不是很了解,所以这里就不再讲解漏斗图的制作和解读了。

首先我们绘制一个漏斗图:

*> ssc install mvmeta
*> ssc install network
use smoking, clear 
network setup d n, studyvar(study) trtvar(trt)
network convert pairs
netfunnel _y _stderr _t1 _t2, random bycomp ///
    addplot(lfit _stderr _ES_CEN) noalpha ///
    scatteroptions(leg(pos(6)))

这幅图的散点颜色是由主题设定的,那么该如何自己设置呢?

最开始我猜想或许可以在 scatteroptions() 里面设置,例如:

netfunnel _y _stderr _t1 _t2, random bycomp ///
    addplot(lfit _stderr _ES_CEN) noalpha ///
    scatteroptions(leg(pos(6)) ///
    mc("102 194 165" "252 141 98" ///
        "141 160 203" "231 138 195" ///
        "166 216 84" "255 217 47"))

但是并没有任何效果。

因此我们得深入 netfunnel 的源代码,研究这个图是如何绘制的。

运行 adoedit netfunnel 打开 netfunnel 的源代码:

adoedit netfunnel 

可以看到绘图代码在 205 行:

twoway `_scat`=`_nc''' , yscale(rev) mc(black) xtitle(`xtitle') ytitle(`ytitle') xline(0, lcol(red)) ylab(`ylabel') xlab(`xlabel'`scatteroptions'|| `_lines' || `addplot'

而散点图生成的代码是在 112~114 行,是通过一个循环生成的。

因此这个图的绘制代码是类似 tw scatter ... || scatter ... || scatter ... 这样的结构,所以直接在最后的选项里添加 mcolors() 是无效的,需要分别在每个图层里面设置。

因此这里我们需要获取绘图数据和完整的代码,进行修改之后再重新绘图。

复制 netfunnel 的代码,在工作目录下面新建一个 netfunnel2.ado 文件。把 205 行附近的代码改成下面的内容:

cap{
    twoway `_scat`=`_nc''' , yscale(rev) mc(black) xtitle(`xtitle') ytitle(`ytitle') xline(0, lcol(red)) ylab(`ylabel') xlab(`xlabel'`scatteroptions' || `_lines' || `addplot'
    save graphdata, replace 
    file open myfile using "plotcode.do", write 
    file write myfile `"twoway `_scat`=`_nc''' , yscale(rev) mc(black) xtitle(`xtitle') ytitle(`ytitle') xline(0, lcol(red)) ylab(`ylabel') xlab(`xlabel') `scatteroptions' || `_lines' || `addplot'"' _n 
    file close myfile 
}

记得文件开头的 program netfunnel, eclass 也要改成 program netfunnel2, eclass

这里 save graphdata, replace 用于保存绘图所需的数据,下面的 file 代码则是为了把绘图代码保存到 plotcode.do 文件中。

运行下面的代码:

netfunnel2 _y _stderr _t1 _t2, random bycomp ///
    addplot(lfit _stderr _ES_CEN) noalpha ///
    scatteroptions(leg(pos(6)))

然后我们就可以在附件中看到 plotcode.do 文件,内容如下:

use graphdata.dta, clear 
twoway sc __000002 __00000O if _dc1==1 & __000000==1 ||sc __000002 __00000O  if _dc2==1 & __000000==1 ||sc __000002 __00000O  if _dc3==1 & __000000==1 ||sc __000002 __00000O  if _dc4==1 & __000000==1 ||sc __000002 __00000O  if _dc5==1 & __000000==1 ||sc __000002 __00000O  if _dc6==1 & __000000==1 , yscale(rev) mc(black) xtitle(Effect size centred at comparison-specific pooled effect ({it:y{sub:iXY}-{&mu}{sub:XY}})) ytitle(Standard error of effect size) xline(0, lcol(red)) ylab(0(0.5)1.5) xlab()  || function y=abs(x/1.96),range(-2.94 2.94) legend(order( 1 "A vs B" 2 "A vs C"  3 "A vs D"  4 "B vs C"  5 "B vs D"  6 "C vs D" ) col(6)) lcol(black) lpat(dash) || lfit _stderr _ES_CEN

直接全选、运行这段代码会报错,大致原因是因为这种 __ 开头的变量导致的,所以我们把所有变量前面都加个 m:

use graphdata.dta, clear 
foreach i of varlist _all {
    ren `i' m`i'
}

然后绘图代码也调整下:

twoway ///
sc m__000002 m__00000O if m_dc1==1 & m__000000==1 || ///
sc m__000002 m__00000O if m_dc2==1 & m__000000==1 || ///
sc m__000002 m__00000O if m_dc3==1 & m__000000==1 || ///
sc m__000002 m__00000O if m_dc4==1 & m__000000==1 || ///
sc m__000002 m__00000O if m_dc5==1 & m__000000==1 || ///
sc m__000002 m__00000O if m_dc6==1 & m__000000==1 , ///
    yscale(rev) mc(black) ///
    xtitle(Effect size centred at comparison-specific pooled effect ({it:y{sub:iXY}-{&mu}{sub:XY}})) ///
    ytitle(Standard error of effect size) ///
    xline(0, lcol(red)) ylab(0(0.5)1.5) xlab() || ///
function y=abs(x/1.96), range(-2.94 2.94) ///
    legend(order( 1 "A vs B" 2 "A vs C"  ///
        3 "A vs D"  4 "B vs C"  5 "B vs D" ///
        6 "C vs D" ) col(6) pos(6)) ///
    lcol(black) lpat(dash) || ///
lfit m_stderr m_ES_CEN

可以看到开头部分的代码其实很容易通过循环生成。下面我们就通过循环生成这部分代码,然后再在每个图层设置颜色:

use graphdata.dta, clear 
foreach i of varlist _all {
 ren `i' m`i'
}

local cmd = "tw"
local colors = `""102 194 165" "252 141 98" "141 160 203" "231 138 195" "166 216 84" "255 217 47""'
forval i = 1/6 {
 local tempcolor: word `i' of `colors'
 local cmd = `"`cmd' (sc m__000002 m__00000O if m_dc`i' == 1 & m__000000 == 1, mc("`tempcolor'"))"'
}
`cmd', yscale(rev) ///
    xtitle(Effect size centred at comparison-specific pooled effect ({it:y{sub:iXY}-{&mu}{sub:XY}})) ///
    ytitle(Standard error of effect size) ///
    xline(0, lcol(red)) ylab(0(0.5)1.5) xlab() || ///
function y=abs(x/1.96), range(-2.94 2.94) ///
    legend(order( 1 "A vs B" 2 "A vs C"  ///
        3 "A vs D"  4 "B vs C"  5 "B vs D" ///
        6 "C vs D" ) col(6) pos(6)) ///
    lcol(black) lpat(dash) || ///
lfit m_stderr m_ES_CEN

gr export pic2.png, width(4800) replace

这样我们就完成了颜色的设置和更改。

直播信息

为了让大家更好的理解本文内容,欢迎各位会员参加明晚 8 点的直播课:「深入源码解决问题!Stata 绘制漏斗图时如何设置散点颜色」

  1. 直播地址:腾讯会议(需要报名 RStata 培训班参加)
  2. 讲义材料:需要购买 RStata 会员,详情可阅读:一起来学习 R 语言和 Stata 啦!学习过程中遇到的问题也可以随时提问!

更多关于 RStata 会员的更多信息可添加微信号 r_stata 咨询:

附件下载(点击文末的阅读原文即可跳转):

https://rstata.duanshu.com/#/brief/course/76fe6acf81ca47bfa0ca87fc5aa614ea


RStata
一起学习 R 语言和 Stata 吧!
 最新文章