在Stata中轻松运用program编写命令
本文作者:王宇晖,北京师范大学—香港浸会大学联合国际学院
本文作者:李春涛,中南财经政法大学金融学院
本文编辑:温和铭
技术总编:李婷婷
Stata&Python云端课程来啦!
为了感谢大家长久以来的支持和信任,爬虫俱乐部为大家送福利啦!!!Stata&Python特惠课程双双上线腾讯课堂~爬虫俱乐部推出了Python编程培训课程、Stata基础课程、Stata进阶课程、Stata文本分析、正则表达式、网络爬虫、基本字符串课程。报名课程即可加入答疑群,对报名有任何疑问欢迎在公众号后台和腾讯课堂留言哦。我们在这篇推文的最后提供了每门课程的课程二维码,大家有需要的话可以直接扫描二维码查看课程详情并进行购买哦~
引言
导读
大家使用Stata时,经常需要对数据做一些特定的处理,为了方便达到我们的目的,这时可能需要自己编写命令。幸运的是,Stata中的program命令可以帮助我们自创命令去解决问题,今天来给大家分享一下program命令的使用方法和一些编写简单程序的例子。
一、program命令的基本语法
在Stata中运用program编写命令时,一般的格式如下所示:
capture program drop pgmname
program [define] pgmname [, [ nclass | rclass | eclass | sclass ]
command collections
end
首先使用capture program drop pgmname检查一下内存中是否已经存在名为pgmname的命令, 如果存在就将其删除。这一行并非必需,但是我们在撰写和调试程序的过程中难免出错,如果程序中间出错,没有运行到end处,即便我们后来将程序修改正确,此时由于内存中已经存在着一个没有定义完的同名命令,Stata会因为重复定义program而报错。根据笔者编程的经验,建议读者在撰写program的时候,务必增加capture program drop命令。
在program [define] pgmname [, [ nclass | rclass | eclass | sclass ]这行中,逗号后面的nclass|rclass|eclass|sclass选项表示所编写命令的返回值类型。一般来说,如果没有返回值,我们可以用nclass选项。返回值一般为rclass类型。 编写命令时,从program define开始,到end结束,中间都是自创命令的内容。
二、编写简单命令
我们先编写一段极其简单的程序,它的功能就是在屏幕上输出一行字。我们用4行程序将编写的新命令定义完之后,再直接调用该命令。整个过程如程序1所示:
capture program drop echo
program define echo
display "Hello World!"
end
echo
程序1定义了一个名字是echo的简单命令,程序的第一行首先试图删除内存中已经存在的名为echo的命令,如果没有则跳过。除去声明定义开始的命令program define和声明定义结束的命令end,程序的内容只有一行:在屏幕上打印出Hello World。程序1的最后一行是调用echo命令,这里调用echo的时候不需要参数,没有返回值,因此在定义的时候我们也没有声明其返回值的类型,当然我们也可以声明其返回值类型为nclass,比如下边的程序2:
capture program drop echo
program define echo, nclass
display "Hello World!"
end
echo
三、编写含有参数的命令
上述程序1和2的功能过于单一,现在我们赋予它新的功能来帮助我们处理数据。比如输入一串字符,让echo命令将我们想要的结果打印到屏幕上。假设我们的目的是执行如下的操作:
我们输入的程序:echo today is a good day!
我们希望屏幕上输出:today is a good day!
此时,字符串“today is a good day!”就是程序echo的参数,但是在用命令echo today is a good day!调用程序echo的时候,这一参数需要以合适的形式传递到程序echo中。最初,Stata定义了一个简单粗暴的参数传递方式:在使用命令echo后边跟上“today is a good day!”的时候,整个字符串“today is a good day!”被放在一个名为“0”的local中,相当于执行了命令:local 0 today is a good day!
有了这一简单粗暴的参数传递方法,我们就可以在定义程序的时候,用local来访问参数了。我们把程序1略微修改,允许它去调用参数,修改后的程序如程序3所示:
capture program drop echo
program define echo, nclass
display "`0'"
end
echo today is a good day!
程序3中存在一个小bug,比如当我们执行echo today is "really" a good day!命令时, 通过参数传递定义了如下的local:
local 0 today is "really" a good day!
这样,程序echo定义中的display "`0'"将被翻译为如下的形式:
display "today is "really" a good day!"
值得注意的是,这里有两组双引号对,但是Stata不能分辨其中的嵌套关系,从而导致命令错误。为此,我们必须把简单的双引号改为Stata的复合双引号,从而得到程序4的定义:
capture program drop echo
program define echo, nclass
display `"`0'"'
end
echo today is "really" a good day!
四、参数传递
我们在程序4中用使用 echo today is "really" a good day! 调用echo命令的时候,参数today is "really" a good day!全部被放入local 0中,但是或许我们在后续的程序中还需要用到参数中的每个片段,为此,Stata进一步把参数即local 0中的内容,按照空格分成K个片段,并另外定义了local 1, local 2,……,local K。我们可以用程序5展示这一过程:
cap program drop echo
program define echo
local K: word count `0'
forvalues i =1/`K' {
disp `"``i''"'
}
end
echo today is "really" a good day!
其中,命令local K: word count `0'是local的扩展函数,它计算出了参数0中通过空格隔开的片段的个数,并储存在local K中,如果参数内容是today is "really" a good day! ,则local K中的内容就是6。随后我们在程序echo的定义中用一个循环,把参数的每个片段打印到屏幕上。这6个local的定义本质上是按照如下的形式进行定义的:
local 1 today
local 2 is
local 3 "really"
local 4 a
local 5 good
local 6 day!
请注意:对于local,其中的内容本身没有字符串的概念,所以"really"这对双引号也被忽略了,因此如下的两个定义是等价的:
local 3 "really"
local 3 really
五、使用macro shift命令遍历参数片段
与此同时,Stata允许我们用命令macro shift重新定义与参数传递相关的local 1, local 2,……,local K。所谓shift,就是把下一个local的值传递给上一个,shift以后,local 2的内容就给了local 1,local 3的内容就给了local 2,以此类推,local K的内容给了local K-1, 最后local K的内容为空,原本local 1中的内容消失。我们可以用程序6展示这一过程:
cap program drop echo
program define echo
while `"`1'"'~="" {
disp `"local 0 `0'"'
disp `"local 1 `1'"'
disp `"local 2 `2'"'
disp `"local 3 `3'"'
macro shift
}
end
echo good day today!
程序6使用了命令macro shift, 整个过程是一个while循环,每次循环我们先判断local 1的内容是否为空,如果不是就依次列出local0、local 1、local 2和local3的内容,然后macro shift,进入下一轮循环。其输出结果见图2:
图2:macro shift的过程展示
从图2的输出结果可以看出,在整个macro shift的过程中,local 1中的内容实际上是遍历了传递给程序echo的参数的每一个片段,因此,如果我们想打印出参数的每个片段,完全可以通过命令macro shift来实现。其次,在macro shift的过程中,local 0中的内容保持不变。有了macro shift命令,程序5的功能可以改写为程序7的形式:
cap program drop echo
program define echo
while `"`1'"'~="" {
disp `"`1'"'
macro shift
}
end
echo today is "really" a good day!
结果如图3所示:
图3:通过macro shift遍历参数片段
程序7即是运用macro shift命令来将每个参数片段在屏幕上打印出来,当local 1中的内容不为空时,进入循环,循环中的程序是把local 1中的内容打印到屏幕上并做一次macro shift。这样一来,第二个片段的内容即local 2中的内容被替换进了local 1,以此类推。每一次循环都会打印出一个参数片段,最后,所有的参数片段被按顺序打印在了屏幕上,结果与程序5中的结果一致。
命令macro shift是在Stata中编写程序的一个非常好用的命令,有了它,我们就可以轻松地将参数以空格为分隔符分割出来。
今天对编写程序的介绍就到这里啦,大家可以自己试一试哦~
腾讯课堂课程二维码
对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!
往期推文推荐
Meta Analysis in Stata17
芒果TV视频弹幕爬取之《我在他乡挺好的》
Stata中的判断神器——confirm命令
cngdf——名义GDP与实际GDP之间的摆渡船最近《扫黑风暴》有点火爆!我从豆瓣评论中发现了这些……
随机森林-Random Forest
复原之神--preserve&restore
合并,“纵”享新丝滑:frameappend & xframeappend什么是全局配置项?|从零开始的Pyecharts(二)帮你拿下数据可视化|从零开始的Pyecharts
Stata助力疫情打卡管理——是谁没有接龙呢?
这十年,《金融研究》的编委和读者偏爱哪些研究话题和文章?【案例展示】Python与数据库交互
学好这一手,英语词典常在手玩转Stata中的数学函数
用spmap看中国空气质量戳穿围城面具:安利&劝退一个专业
走进图文并茂的攻略世界
玩转word文档“大变身”——wordconvert
简述递归
OpenCV库——轻松更换证件照背景色800万年薪!还有谁?!
千古伤心词人,词伤几何?
去哪儿网攻略爬取——跟我一起去大理吧
"有你才有团"——Stata爬取王者荣耀英雄海报
如何获取衡量股民情绪的指标?|东方财富股吧标题爬虫
利用Python构建马科维茨有效边界
rangestat,让统计量灵活滚动起来!
听说这样做立项成功率更高哦
关于我们
微信公众号“Stata and Python数据分析”分享实用的Stata、Python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。
武汉字符串数据科技有限公司一直为广大用户提供数据采集和分析的服务工作,如果您有这方面的需求,请发邮件到statatraining@163.com,或者直接联系我们的数据中台总工程司海涛先生,电话:18203668525,wechat: super4ht。海涛先生曾长期在香港大学从事研究工作,现为知名985大学的博士生,爬虫俱乐部网络爬虫技术和正则表达式的课程负责人。
此外,欢迎大家踊跃投稿,介绍一些关于Stata和Python的数据处理和分析技巧。
投稿邮箱:statatraining@163.com投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。