查看原文
其他

Stata:如何根据自己的需求输出代码结果到 word 文档?以 rdrandinf 命令为例

RStata RStata 2023-10-24

为了让大家更好的理解下面的代码,欢迎各位培训班会员参加明晚 8 点的直播课:「Stata:如何根据自己的需求输出代码结果到 word 文档?以 rdrandinf 命令为例」

课程主页(点击文末的阅读原文即可跳转):https://rstata.duanshu.com/#/brief/course/4b88e52cef584cf38298f1e389eb20df  
🔥购买 SSVIP 会员即可参加该课程:999元/长期有效,详情可添加微信 r_stata 咨询了解!

最近有个小伙伴问了这样一个问题,他需要把 rdrandinf 命令运行的结果保存到 word 文档中,但是没找到现成的输出命令。下面是一个简单的示例:

use rdlocrand_senate.dta, clear
* 不做变换
rdrandinf demvoteshfor2 demmv, seed(50) p(0) reps(10) interfci(.05) wl(-.75) wr(.75)

*> Selected window = [-.75 ; .75]
*>
*> Running randomization-based test...
*> Randomization-based test complete.
*>
*>
*> Inference for sharp design
*>
*>
*> Cutoff c = 0.00 | Left of c Right of c Number of obs = 1297
*> ------------------+----------------------- Order of poly = 0
*> Number of obs| 595 702 Kernel type = uniform
*> Eff. Number of obs| 15 22 Reps = 10
*> Mean of outcome| 42.808 52.497 Window = set by user
*> S.D. of outcome| 7.042 7.742 H0: tau = 0.000
*> Window| -0.750 0.750 Randomization = fixed margins
*>
*> Outcome: demvoteshfor2. Running variable: demmv.
*> --------------------------------------------------------------------------------
*> | Finite sample Large sample
*> | --------------- -------------------------------
*> Statistic| T P>|T| P>|T| Power vs d = 3.52
*> ------------------+-------------------------------------------------------------
*> Diff. in means| 9.689 0.000 0.000 0.300
*> --------------------------------------------------------------------------------
*>
*> Confidence interval under interference
*> ------------------------------------------
*> Statistic| [95% Conf. Interval]
*> ------------------+-----------------------
*> Diff. in means| 6.713 15.711
*> ------------------------------------------
*>
*> . return list
*>
*> scalars:
*> r(wl) = -.75
*> r(wr) = .75
*> r(N) = 37
*> r(N_left) = 15
*> r(N_right) = 22
*> r(p) = 0
*> r(int_lb) = 6.71283355192705
*> r(int_ub) = 15.71115699247881
*> r(obs_stat) = 9.68949952559038
*> r(asy_pval) = .0000795467132186
*> r(randpval) = 0
*>
*> macros:
*> r(seed) : "50"

除此之外还有两个模型,就不展示结果了:

* 一阶变换
rdrandinf demvoteshfor2 demmv, seed(50) p(1) reps(10) interfci(.05) wl(-.75) wr(.75)
return list

* 二阶变换
rdrandinf demvoteshfor2 demmv, seed(50) p(2) reps(10) interfci(.05) wl(-.75) wr(.75)
return list

想要输出这样的结果:

虽然直接手抄结果整理表格也不是很麻烦,但是不利于重复研究(例如,数据更新了,表格就得重新手抄一遍了),所以我们可以考虑自编一个程序用于输出这样的表格。

首先我们需要的数据都在返回值里面(return list 的结果)

所以我们需要先编写一个能够存储每个 rdrandinf 结果的命令:

capture program drop store_retlist
program define store_retlist
syntax anything, cmd(string)
cap log close
log using `anything', replace text
`cmd'
ret list
log close
end

也可以把这段代码存储到 store_retlist.ado 文件中方便之后使用(记得文件的最后留一行空行)。

store_retlist 命令可以自动运行 cmd() 选项的语句,然后把代码运行结果和返回值结果存储到 log 文件中:

use rdlocrand_senate.dta, clear
* 不做变换
store_retlist retlist1, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(0) reps(10) interfci(.05) wl(-.75) wr(.75))
store_retlist retlist2, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(1) reps(10) interfci(.05) wl(-.75) wr(.75))
store_retlist retlist3, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(2) reps(10) interfci(.05) wl(-.75) wr(.75))

运行上面的代码就可以得到三个文件了:retlist1.log,retlist2.log 和 retlist3.log,分别处理三个文件。以 retlist1.log 为例测试:

infix strL retlist1 1-20000 using "retlist1.log", clear
keep if index(retlist1, "r(")
split retlist1, parse("=" ":")

这样我们就可以循环处理这三个文件了:

* 处理三个 log 文件
cap mkdir "retlist"
foreach i in retlist1 retlist2 retlist3 {
infix strL `i' 1-20000 using "`i'.log", clear
keep if index(`i', "r(")
split `i', parse("=" ":")
drop `i'
ren `i'1 id1
ren `i'2 `i'
gen id = _n
save retlist/`i', replace
}

然后把三个文件 merge 起来,为了方便后面的命令封装,我们使用 mergeall 进行合并:

clear
* mergeall 安装:ssc install mergeall
mergeall id using "retlist", dta
drop id
foreach i in retlist1 retlist2 retlist3 {
replace `i' = subinstr(`i', `"""', "", .)
destring `i', replace
}
replace id1 = subinstr(id1, " ", "", .)
save retdata, replace

list

*> +-------------------------------------------------+
*> | id1 retlist1 retlist2 retlist3 |
*> |-------------------------------------------------|
*> 1. | r(wl) -.75 -.75 -.75 |
*> 2. | r(wr) .75 .75 .75 |
*> 3. | r(N) 37 37 37 |
*> 4. | r(N_left) 15 15 15 |
*> 5. | r(N_right) 22 22 22 |
*> |-------------------------------------------------|
*> 6. | r(p) 0 1 2 |
*> 7. | r(int_lb) 6.7128336 11.356525 19.277953 |
*> 8. | r(int_ub) 15.711157 21.576708 31.815862 |
*> 9. | r(obs_stat) 9.6894995 15.296517 24.143527 |
*> 10. | r(asy_pval) .00007955 .06596567 .10790754 |
*> |-------------------------------------------------|
*> 11. | r(randpval) 0 0 0 |
*> 12. | r(seed) 50 50 50 |
*> +-------------------------------------------------+

然后我们就可以使用 putdocx 把结果整理出我们想要的样子输出到 docx 文档了:

* 输出到 docx 文档
putdocx clear
putdocx begin, pagesize(A4) font(Times New Roman)
putdocx paragraph, spacing(after, 0) halign(center) valign(center)
* 标题
putdocx text (`"rdrandinf 估计结果输出"'), font("Times New Roman", 18) linebreak

* 表格 8x4
putdocx table mytable = (8, 4), width(100%) halign(center) border(all, nil) border(top) border(bottom) cellmargin(top, 0.1cm) cellmargin(bottom, 0.1cm) cellmargin(left, 0.1cm) cellmargin(right, 0.1cm)

* 表头
putdocx table mytable(1, 1) = ("变量")
forval i = 1/3{
putdocx table mytable(1, `=`i'+1') = ("(`i')")
}

* 估计结果
putdocx table mytable(2, 1) = ("demmv0")
preserve
keep if id1 == "r(obs_stat)" | id1 == "r(randpval)" | id1 == "r(asy_pval)"
forval i = 1/3{
if `=retlist`i'[3]' < 0.1 local star = "*"
if `=retlist`i'[3]' < 0.05 local star = "**"
if `=retlist`i'[3]' < 0.01 local star = "***"
putdocx table mytable(2, `=`i'+1') = (`"`=string(`=retlist`i'[1]', "%6.2f")'`star'"'), linebreak
putdocx table mytable(2, `=`i'+1') = (`"[`=string(`=retlist`i'[2]', "%6.4f")']"'), append
}
restore

* 95% 置信区间
putdocx table mytable(3, 1) = ("95% 置信区间")
preserve
keep if id1 == "r(int_lb)" | id1 == "r(int_ub)"
forval i = 1/3{
putdocx table mytable(3, `=`i'+1') = (`"[`=string(`=retlist`i'[1]', "%6.2f")', `=string(`=retlist`i'[2]', "%6.2f")']"')
}
restore


* 对 y 多项式变换阶数
putdocx table mytable(4, 1) = ("对 y 多项式变换阶数")
preserve
keep if id1 == "r(p)"
forval i = 1/3{
putdocx table mytable(4, `=`i'+1') = (`=retlist`i'[1]')
}
restore

* 左窗口
putdocx table mytable(5, 1) = ("左窗口")
preserve
keep if id1 == "r(wl)"
forval i = 1/3{
putdocx table mytable(5, `=`i'+1') = (`"`=string(`=retlist`i'[1]', "%6.2f")'"')
}
restore

* 右窗口
putdocx table mytable(6, 1) = ("右窗口")
preserve
keep if id1 == "r(wr)"
forval i = 1/3{
putdocx table mytable(6, `=`i'+1') = (`"`=string(`=retlist`i'[1]', "%6.2f")'"')
}
restore

* 左侧 N
putdocx table mytable(7, 1) = ("左侧 N")
preserve
keep if id1 == "r(N_left)"
forval i = 1/3{
putdocx table mytable(7, `=`i'+1') = (`"`=retlist`i'[1]'"')
}
restore

* 右侧 N
putdocx table mytable(8, 1) = ("右侧 N")
preserve
keep if id1 == "r(N_right)"
forval i = 1/3{
putdocx table mytable(8, `=`i'+1') = (`"`=retlist`i'[1]'"')
}
restore

* 所有的单元格居中
putdocx table mytable(., .), valign(center) halign(center)

* 为 第一行添加上下框线
putdocx table mytable(1, .), border(top, single) border(bottom, single)

* 保存
putdocx save "mytable.docx", replace

这样就得到了我们想要的结果:

进一步我们还可以把这段程序封装成命令:

capture program drop rdrandinf2docx
program define rdrandinf2docx
syntax anything, Prefix(string) Count(string) [VARNAME(string) TItle(string) FONT(string) FONTSize(string) FILEname(string)]
if "`title'" == "" local title = "rdrandinf 估计结果"
if "`varname'" == "" local varname = "变量名"
if "`font'" == "" local font = "Times New Roman"
if "`fontsize'" == "" local fontsize = 18
if "`filename'" == "" local filename = 18
qui{
* 处理三个 log 文件 (文件夹的名字就不动了)
cap mkdir "retlist"
foreach i in `anything' {
infix strL `i' 1-20000 using "`i'.log", clear
keep if index(`i', "r(")
split `i', parse("=" ":")
drop `i'
ren `i'1 id1
ren `i'2 `i'
gen id = _n
save retlist/`i', replace
}

clear
mergeall id using "retlist", dta
drop id
foreach i in `anything' {
replace `i' = subinstr(`i', `"""', "", .)
destring `i', replace
}
replace id1 = subinstr(id1, " ", "", .)
save retdata, replace

* 输出到 docx 文档
putdocx clear
putdocx begin, pagesize(A4) font(Times New Roman)
putdocx paragraph, spacing(after, 0) halign(center) valign(center)
* 标题
putdocx text (`"`title'"'), font("`font'", `fontsize') linebreak

* 表格 8x4
putdocx table mytable = (8, `=`count'+1'), width(100%) halign(center) border(all, nil) border(top) border(bottom) cellmargin(top, 0.1cm) cellmargin(bottom, 0.1cm) cellmargin(left, 0.1cm) cellmargin(right, 0.1cm)

* 表头
putdocx table mytable(1, 1) = ("变量")
forval i = 1/`count'{
putdocx table mytable(1, `=`i'+1') = ("(`i')")
}

* 估计结果
putdocx table mytable(2, 1) = ("`varname'")
preserve
keep if id1 == "r(obs_stat)" | id1 == "r(randpval)" | id1 == "r(asy_pval)"
forval i = 1/`count'{
if `=retlist`i'[3]' < 0.1 local star = "*"
if `=retlist`i'[3]' < 0.05 local star = "**"
if `=retlist`i'[3]' < 0.01 local star = "***"
putdocx table mytable(2, `=`i'+1') = (`"`=string(`=retlist`i'[1]', "%6.2f")'`star'"'), linebreak
putdocx table mytable(2, `=`i'+1') = (`"[`=string(`=retlist`i'[2]', "%6.4f")']"'), append
}
restore

* 95% 置信区间
putdocx table mytable(3, 1) = ("95% 置信区间")
preserve
keep if id1 == "r(int_lb)" | id1 == "r(int_ub)"
forval i = 1/`count'{
putdocx table mytable(3, `=`i'+1') = (`"[`=string(`=retlist`i'[1]', "%6.2f")', `=string(`=retlist`i'[2]', "%6.2f")']"')
}
restore

* 对 y 多项式变换阶数
putdocx table mytable(4, 1) = ("对 y 多项式变换阶数")
preserve
keep if id1 == "r(p)"
forval i = 1/`count'{
putdocx table mytable(4, `=`i'+1') = (`=retlist`i'[1]')
}
restore

* 左窗口
putdocx table mytable(5, 1) = ("左窗口")
preserve
keep if id1 == "r(wl)"
forval i = 1/`count'{
putdocx table mytable(5, `=`i'+1') = (`"`=string(`=retlist`i'[1]', "%6.2f")'"')
}
restore

* 右窗口
putdocx table mytable(6, 1) = ("右窗口")
preserve
keep if id1 == "r(wr)"
forval i = 1/`count'{
putdocx table mytable(6, `=`i'+1') = (`"`=string(`=retlist`i'[1]', "%6.2f")'"')
}
restore

* 左侧 N
putdocx table mytable(7, 1) = ("左侧 N")
preserve
keep if id1 == "r(N_left)"
forval i = 1/`count'{
putdocx table mytable(7, `=`i'+1') = (`"`=retlist`i'[1]'"')
}
restore

* 右侧 N
putdocx table mytable(8, 1) = ("右侧 N")
preserve
keep if id1 == "r(N_right)"
forval i = 1/`count'{
putdocx table mytable(8, `=`i'+1') = (`"`=retlist`i'[1]'"')
}
restore

* 所有的单元格居中
putdocx table mytable(., .), valign(center) halign(center)

* 为 第一行添加上下框线
putdocx table mytable(1, .), border(top, single) border(bottom, single)
}
* 保存
putdocx save "`filename'.docx", replace

* 删除无用文件
foreach i in `anything' {
cap erase "`i'.log"
cap erase "retlist/`i'.dta"
}
cap erase retdata.dta
end

把上面的代码保存到 rdrandinf2docx.ado 文件中即可(记得文件的最后留一行空行)。

然后就可以非常方便的使用这个命令啦!例如下面创建一个含有 5 个模型的表格:

clear all
use rdlocrand_senate.dta, clear
* 5 个模型
store_retlist retlist1, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(0) reps(10) interfci(.05) wl(-.75) wr(.75))
store_retlist retlist2, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(1) reps(10) interfci(.05) wl(-.75) wr(.75))
store_retlist retlist3, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(2) reps(10) interfci(.05) wl(-.75) wr(.75))
store_retlist retlist4, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(4) reps(10) interfci(.05) wl(-.75) wr(.75))
store_retlist retlist5, cmd(rdrandinf demvoteshfor2 demmv, seed(50) p(5) reps(10) interfci(.05) wl(-.75) wr(.75))

rdrandinf2docx retlist1 retlist2 retlist3 retlist4 retlist5, prefix(retlist) count(5) varname(demmv0) file(mytable2)

虽然代码复杂了点,但是使用起来更方便了!

直播信息

为了让大家更好的理解上面的代码,欢迎各位培训班会员参加明晚 8 点的直播课:「Stata:如何根据自己的需求编程输出代码结果到 word 文档?以 rdrandinf 命令为例」

  1. 直播地址:腾讯会议(需要报名 RStata 培训班参加)
  2. 讲义材料:需要报名 RStata 培训班,详情可阅读:写论文不会处理数据怎么办?R 语言、Stata、计量经济学如何入门?

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


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存