3  命令结构

本章中,我们将系统学习Stata的语法结构。

3.1 Stata的语法范式

Stata所有命令都遵循如下格式要求:

[by varlist:] command [varlist] [using filename] [if exp] [in range] [weight] [, options]

这里有一些格式上的设定是在Stata中通用的,了解这些规则对于大家阅读help文档具有很大的好处。

  • 方括号[]表示可有可无的内容,
  • 斜体内容(例如varlist)表示需要用其他内容代替
  • 如果命令名称下有下划线的,代表缩写的最小程度

按照这个规则,显然只有command(命令名称)是必不可少的,其他的部分都是可有可无。到目前为止,大家已经学习了多条命令,例如cd, use, save, import等都属于是command。

Stata命令范式中每一部分的功能如下(先有一个大致的印象,后续我们会结合例子具体介绍,在后续的学习过程中也会逐步加强对这部分的理解):

表 3.1: Stata命令语法结构说明
名称 含义
bysort varlist 按照varlist分组,在每个分组内分别执行命令,分组依据可以是多个变量也可以是单个变量,如果分组依据单个变量,常写作varname常用。
command 命令主体。Stata命令中唯一必须有的内容。
varlist 变量列表,是命令command的作用对象,如果命令后没有具体的变量则通常意味着command的操作是针对当前整个数据集(全部变量),常用。
using filename 命令所使用的文件filename,常用。
if exp 代表命令command的执行是否是针对满足条件的观测值(行)。在Stata中,命令默认是按行来执行的(也就是先执行第一行、然后第二行、依次类推)1,如果命令中没有逻辑条件判断,那就是针对所有行都执行,但如果有了逻辑条件判断,这个执行就不是针对所有行,而是只有满足条件的行执行,不满足条件的行不执行。换句话说,命令是否执行取决于该条件判断语句(即exp)的结果,如果一行数据对应的逻辑表达式运算结果为真就执行该命令,如果一行数据对应的逻辑表达式运算结果为假则不执行命令。常用。
in range in 后需要加一个数字范围,代表变量执行是在指定的某一(些)行,与 if exp的功能类似,常用。
weight 对结果按照某列数据进行加权,不太常用

3.2 命令名称 Command

命令名称是Stata代码的核心内容,是一条命令中唯一必须要存在的部分。 [by varlist:] command [varlist] [using filename] [if exp] [in range] [weight] [, options]

sysuse auto, clear //打开数据Trd.xlsx,是A股股票的基本信息文件
summarize 
sum // 是命令summarize的简写
su // 进一步的简写
s // 出现错误简写的前提是不能引起混淆,无法识别,简写的程度看help文件中命令的下划线
help summarize // 查看syntax部分的 summarize的下划线,确定了最大简写程度

命令可以简写,例如summarize可以最简写成su,也就是说写成sumsummariz之间的内容都可以被识别。能够精简的最短内容可以通过帮助文件看出,命令名的下划线的内容就是可以最大简写的程度。

summarize命令帮助文件Syntax截图

3.3 变量列表 varlist

[by varlist:] command [varlist] [using filename] [if exp] [in range] [weight] [, options]

varlist代表多个变量或者一个变量,多个变量之间要用空格隔开。

sysuse auto, clear 
summarize //很多命令可以单独使用,单独使用时一般都是针对所有变量进行操作,等同于comamnd _all
summarize _all //与上面的一行命令等价

summarize turn 
su turn // 
sum turn  // 命令缩写
sum tu // 命令缩写的同时,变量名也能缩写
sum t // 这个报错,缩写的前提是能够唯一识别该变量

sort length // 将数据按照变量length取值的升序排序
browse 
sort length price // 将数据按照变量length和price取值的升序排序
browse  

3.4 外部文件 using filename

只在涉及到文件处理的命令中出现。例如append using filename

3.5 条件表达式 if exp

条件表达式用于限定命令的作用范围是数据集的全部行还是部分行。

[by varlist:] command [varlist] [using filename] [if exp] [in range] [weight] [, options]

if exp的作用是对命令的作用范围(哪些observation执行、哪些observation不执行)进行限定,表达式(exp)的结果为真命题的observation执行命令;当表达式exp为假命题的observation则不执行命令。

sysuse auto, clear 
tabulate rep78
list trunk turn rep78 if rep78 == 2 
list if rep78 == 2
browse trunk turn rep78 if rep78 == 5
browse if rep78 == 5 

if语句也可以和_n_N等结合起来,直接依据行数将命令限定与特定的哪些行来执行。 _n_N都是系统保留的字段。其中_N代表数据中的总行数或者最大行数或者最后一行的行数。_n代表每一条观测值的行号,取值为1,2,…,_N

drop if _n == 1 // 删除第1行
drop if _n == 2 //删除第2行
drop if _n >= 1 & _n <= 5 // 删除前5行,符号&表示两个条件同时成立,即逻辑“与”运算
drop if _n >=-5 & _n <= -1 //删除后5行,符号&表示两个条件同时成立,即逻辑“与”运算
drop if _n > (_N – 5) // 删除最后5行

逻辑表达式也可以是一些简单逻辑的复合运算,Stata中逻辑复合运算包括:与、或、非,对应的运算符号是&|!。与、或、非的运算逻辑如下(这部分内容我们将会在后续章节中继续学习):

与运算的计算逻辑
逻辑判断A 逻辑判断B 运算结果
A=真 B=真 A & B = 真
A=真 B=假 A & B = 假
A=假 B=真 A & B = 假
A=假 B=假 A & B = 假
或运算的计算逻辑
逻辑判断A 逻辑判断B 运算结果
A=真 B=真 A | B = 真
A=真 B=假 A | B = 真
A=假 B=真 A | B = 真
A=假 B=假 A | B = 假
非运算的计算逻辑
逻辑判断A 运算结果
A=真 !A = 假
A=假 !A = 真

3.6 范围 in

[by varlist:] command [varlist] [using filename] [if exp] [in range] [weight] [, options]

与if和_n, _N连用的效果一样,同样是限定命令的执行在特定行内执行,在其他行内不执行。in后跟着的数字(序列):

  1. 如果是一个单独的数字,就是对应的行号
  2. 如果是m/n (其中n>m)的形式,就是从m到n之间的所有整数(每次加1)
  3. 如果是m(k)n的形式,就是从m开始,每次步长值为k的递增序列。
  4. m(1)n 与m/n等价
  5. 负数代表倒数的行数,如-5表示倒数第5行,-1表示倒数第1行(也就是最后一行)
sysuse auto, clear 
drop in 1 // 删除第1行
drop in 2 // 删除第2行
drop in 1/5 //删除1到5行,也就是1,2,3,4,5等前5行
drop in 1(1)5 // 不能识别的语法
drop in -5/-1 //删除最后5行,也就是-5,-4,-3,-2,-1等最后5行

3.7 分组操作 by

[by varlist:] command [varlist] [using filename] [if exp] [in range] [weight] [, options]

by是Stata命令中的前缀prefix中最为常见的一个,by的作用是将所有的observation按照varlist的取值分组,然后command在每一个分组内分别执行。在使用by对数据分组执行命令之前,必须先对数据进行排序,排序命令是sort varlist,按照varlist中的变量的升序[排序命令我们后续再展开。]依次排序。

sysuse auto, clear 
sort foreign 
by foreign: summarize price 
// 也可以将sort和by合并写成bysort 
bysort foreign: summarize price

tabulate rep78, missing
sort rep78 
by rep78: summarize price 

bysort foreign: summarize price 

. sysuse auto, clear 
(1978 automobile data)

. sort foreign 

. by foreign: summarize price 

-------------------------------------------------------------------------------
-> foreign = Domestic

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         52    6072.423    3097.104       3291      15906

-------------------------------------------------------------------------------
-> foreign = Foreign

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         22    6384.682    2621.915       3748      12990


. // 也可以将sort和by合并写成bysort 
. bysort foreign: summarize price

-------------------------------------------------------------------------------
-> foreign = Domestic

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         52    6072.423    3097.104       3291      15906

-------------------------------------------------------------------------------
-> foreign = Foreign

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         22    6384.682    2621.915       3748      12990


. 
. tabulate rep78, missing

     Repair |
record 1978 |      Freq.     Percent        Cum.
------------+-----------------------------------
          1 |          2        2.70        2.70
          2 |          8       10.81       13.51
          3 |         30       40.54       54.05
          4 |         18       24.32       78.38
          5 |         11       14.86       93.24
          . |          5        6.76      100.00
------------+-----------------------------------
      Total |         74      100.00

. sort rep78 

. by rep78: summarize price 

-------------------------------------------------------------------------------
-> rep78 = 1

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |          2      4564.5    522.5519       4195       4934

-------------------------------------------------------------------------------
-> rep78 = 2

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |          8    5967.625    3579.357       3667      14500

-------------------------------------------------------------------------------
-> rep78 = 3

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         30    6429.233     3525.14       3291      15906

-------------------------------------------------------------------------------
-> rep78 = 4

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         18      6071.5    1709.608       3829       9735

-------------------------------------------------------------------------------
-> rep78 = 5

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         11        5913    2615.763       3748      11995

-------------------------------------------------------------------------------
-> rep78 = .

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |          5      6430.4    3804.322       3799      12990


. 
. bysort foreign: summarize price 

-------------------------------------------------------------------------------
-> foreign = Domestic

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         52    6072.423    3097.104       3291      15906

-------------------------------------------------------------------------------
-> foreign = Foreign

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         22    6384.682    2621.915       3748      12990


. 

这里变量foreign的取值其实并不是DomesticForeign,而是0和1,我们看到的是取值标签(value label)。如果通过browse查看的话,其实可以发现变量foreign的取值是蓝色的,既不是字符的红色、也不是数值的黑色:

图 3.1: 取值标签value label
tabulate foreign // foreign的取值有两个,"Foreign"和"Domestic",但其实是标签
br if foreign == 1 
br if foreign == 0 

我们可以使用label相关的命令查看取值标签:

label dir // 会显示数据中存在名为origin的取值标签
label list origin // 进一步查看origin标签的内容

. label dir // 会显示数据中存在名为origin的取值标签
origin

. label list origin // 进一步查看origin标签的内容
origin:
           0 Domestic
           1 Foreign

. 

另外,需要指出的是,排序sort和分组操作by都是可以针对多个变量进行。

3.8 其他选项options

[by varlist:] command [varlist] [if exp] [in range] [weight] [, options]

许多命令中都可以通过option来丰富命令的执行。例如我们在import excel命令中通过firstrow将第一行设定为变量名。再例如,summarize命令中默认会给出:观测值数量Obs, 均值Mean,标准差Std.Dev.,最小值Min和最大值Max。如果我们还想知道中位数,这时候可以在summarize之后增加, detail,这会显示更加消息的统计信息。

sysuse auto,clear
sum price 
sum price, detail 

. sysuse auto,clear
(1978 automobile data)

. sum price 

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       price |         74    6165.257    2949.496       3291      15906

. sum price, detail 

                            Price
-------------------------------------------------------------
      Percentiles      Smallest
 1%         3291           3291
 5%         3748           3299
10%         3895           3667       Obs                  74
25%         4195           3748       Sum of wgt.          74

50%       5006.5                      Mean           6165.257
                        Largest       Std. dev.      2949.496
75%         6342          13466
90%        11385          13594       Variance        8699526
95%        13466          14500       Skewness       1.653434
99%        15906          15906       Kurtosis       4.819188

. 

3.9 加权 weight

[by varlist:] command [varlist] [using filename] [if exp] [in range] [weight] [, options]

加权并不常见,多用于汇总表中的加权计算。例如下标中是一个虚拟的高考成绩分段统计表,是640分及以上成绩一分一段的人数统计,第一列为高考分数,第二列为对应分数的人数。现在我们要计算640分以上全部考生的平均分。

表 3.2: 虚拟的分数段人数分布
score num
650 193
649 26
648 23
647 16
646 21
645 26
644 32
643 23
642 38
641 29
640 38

表 3.2 中给出的是汇总后的分数,即每一个分数上的人数。

在之前的课程中,我们介绍过命令summarize varname可以给出变量的描述性统计,其中就包括均值。但是如果直接用命令summarize分数得到的平均分不能反映出真实的均值。如果要计算这些学生的平均成绩,应该用每个分数上所有人的成绩加总再除以所有的人数。即:

6650\times 193/\sum(193,\cdots, 38)+\cdots+640/\sum(193,\cdots, 38)

这个公式可以 理解成score变量按照num变量的加权平均值,权重是每个分数上人数占全部人数的比例。可以使用summarize结合加权的方式,用一条命令来实现计算均值:

clear 
input score num
650 193
649 26
648 23
647 16
646 21
645 26
644 32
643 23
642 38
641 29
640 38
end 
summarize score
summarize score [weight=num]

. clear 

. input score num

         score        num
  1. 650     193
  2. 649     26
  3. 648     23
  4. 647     16
  5. 646     21
  6. 645     26
  7. 644     32
  8. 643     23
  9. 642     38
 10. 641     29
 11. 640     38
 12. end 

. summarize score

    Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
       score |         11         645    3.316625        640        650

. summarize score [weight=num]
(analytic weights assumed)

    Variable |     Obs      Weight        Mean   Std. dev.       Min        Max
-------------+-----------------------------------------------------------------
       score |      11         465    646.4903   3.884966        640        650

. 

3.10 习题

  1. 梳理到目前为止学过的命令,结合其帮助文档,熟悉命令的语法结构。

本章附录

本章代码汇总


// command 
sysuse auto, clear 
summarize 
sum // 是命令summarize的简写
su // 进一步的简写
s // 出现错误简写的前提是不能引起混淆,无法识别,简写的程度看help文件中命令的下划线
help summarize // 查看syntax部分的 summarize的下划线,确定了最大简写程度

// varlist 
summarize //很多命令可以单独使用,单独使用时一般都是针对所有变量进行操作,等同于comamnd _all
summarize _all //与上面的一行命令等价

summarize turn 
su turn // 
sum turn  // 命令缩写
sum tu // 命令缩写的同时,变量名也能缩写
sum t // 这个报错,缩写的前提是能够唯一识别该变量

sort length // 将数据按照变量length取值的升序排序
browse 
sort length price // 将数据按照变量length和price取值的升序排序
browse  

// if exp
sysuse auto, clear 
tabulate rep78
list trunk turn rep78 if rep78 == 2 
list if rep78 == 2
browse trunk turn rep78 if rep78 == 5
browse if rep78 == 5 

sysuse auto, clear 
drop if _n == 1 // 删除第1行
drop if _n == 2 //删除第2行
drop if _n >= 1 & _n <= 5 // 删除前5行,符号&表示两个条件同时成立,即逻辑“与”运算
drop if _n >=-5 & _n <= -1 //删除后5行,符号&表示两个条件同时成立,即逻辑“与”运算
drop if _n > (_N – 5) // 删除最后5行

// in range
sysuse auto, clear 
drop in 1 // 删除第1行
drop in 2 // 删除第2行
drop in 1/5 //删除1到5行,也就是1,2,3,4,5等前5行
drop in 1(1)5 // 不能识别的语法
drop in -5/-1 //删除最后5行,也就是-5,-4,-3,-2,-1等最后5行

// by varlist
sysuse auto, clear 
sort foreign 
by foreign: summarize price 
// 也可以将sort和by合并写成bysort 
bysort foreign: summarize price

tabulate foreign // foreign的取值有两个,"Foreign"和"Domestic",但其实是标签
br if foreign == 1 
br if foreign == 0 

label dir 
label list origin

// weigth 
clear 
input score num
650 193
649 26
648 23
647 16
646 21
645 26
644 32
643 23
642 38
641 29
640 38
summarize score
summarize score [weight=num]

  1. Stata中所有命令的执行,是对整个数据中的每一行一次执行的,即先执行第一行,然后是第二行,以此类推。但是用户并不需要使用循环语句声明这一方法,因为这是Stata中默认的处理方案。↩︎