Stata-Mata系列 (二):Mata与Stata的交互

发布时间:2021-01-13 阅读 1335

Stata连享会   主页 || 视频 || 推文 || 知乎

温馨提示: 定期 清理浏览器缓存,可以获得最佳浏览体验。

New! lianxh 命令发布了:
随时搜索连享会推文、Stata 资源,安装命令如下:
. ssc install lianxh
使用详情参见帮助文件 (有惊喜):
. help lianxh

课程详情 https://gitee.com/arlionn/Course   |   lianxh.cn

课程主页 https://gitee.com/arlionn/Course


作者: 严子凯 (中山大学)
邮箱:yanzk@mail2.sysu.edu.cn

指导老师: 连玉君 (中山大学)
邮箱:arlionn@163.com


目录



导师寄语:

2005 年,我读博二,Stata 发布了 9.0。

一个最大的变化就是引入了 Mata 语言,她对 Stata 的意义不亚于中国加入 WTO:Stata 的运算速度、处理能力都因为 Mata 的引入而得到质的提升。当然,对于多数用户而言,这种变化无从感知。然而,一旦你想要自己编写程序,处理一些相对复杂的问题时,Mata 就变成一个「不敢轻易去爱」,但又「不得不爱」,最终「爱了,就不能自拔」的尤物。

我这么说不是危言耸听。因为,Mata 很强大,Mata 不容易掌握。她是烈马,是埃及艳后,^-^。

子凯有点不同。他花了一周,啃完了 Stata 公司元老的名著的 1/3:Gould, William. 2018. The Mata Book. College Station, TX: Stata Press. 然后就哗哗地编写了面板平滑转移模型,优化版本的「模拟退火算法」,……,以至于我无法把他拉回期末考试的复习中来。

呈现给大家的这篇推文是子凯同学在完成上述程序过程中记录的一部分笔记,随后,期末考试结束后他会进一步整理、分享。

ps,子凯是岭南学院大三的学生,这学期上我的「金融计量」,一直坐在第一排左手边第一个座位上。  
开始读下文之前,给各位分享一份特殊的文件:「Thirty Years with Stata: A Retrospective」。这里 是 Stata 官网版本。


连玉君
2021/1/9 11:58

Mata 作为 Stata 的高级编程语言,其数据命令程序的调用需要单独的语句声明并执行。本文结合 句法实例,重点介绍 Mata 与 Stata 的交互语言,尝试为读者搭建起融汇两者的桥梁,打破初学者心中的 Mata 应用壁垒。

如果您与 Mata 素未谋面,可以先看看连享会此前的推文 Stata - Mata系列 (一):Mata 入门

1. 为什么存在交互问题

对于 Mata 的初学者来说,经常会有如下对答:

疑问: Stata 里面运行的 Mata 为什么还会和 Stata 存在交互问题呢?

回答: 因为 Mata 和 Stata 采用两套不同的语法命令,并且掉用两个不同的内存空间。

具体而言:当我们打开 Stata 软件时,系统会调用一部分内存用于储存之后调用和生成的 Stata 相关数据。如果我们将整台电脑的内存比作一家 酒店,那么我们可以将这部分内存空间视为:「Stata 房间」。 Mata 环境也拥有一套独立的内存空间,我们将其视为「Mata 房间」。

我们知道执行 Mata 命令前需要调用 Mata 环境,即告诉 Stata 我们接下来要执行 Mata 命令(命令是:Mata 或 mata:),而在之后需要返回 Stata 环境前,同样需要命令告知 Stata 我们要离开 Mata 环境回到 Stata 环境了。(命令是:end

演示如下:

我们在 「Stata 房间」 中生成了字符串型标量 str1 和 数值型标量numb1,然后在 「Mata 房间」 中生成了字符串型标量 str2 和 数值型标量numb2

. scalar str1 = "I love lianxh."
. scalar numb1 = 666888

.  mata
------------------------------------------
: str2  = "I love lianxh, too!" 
: numb2 = 888666
: end
------------------------------------------

当我们输入 Mata: 命令进入到 Mata 环境中后,我们相当于离开了 「Stata 房间」,并且进入到了 「Mata 房间」 中,因而接下来生成的所有数据将储存在 「Mata 房间」 之中。同时,当我们输入 end 命令回到 Stata 环境后,内存空间也对应从 「Mata 房间」 切换回 「Stata 房间」 。

注意,无论是在输入 Mata: 命令进入到 Mata 环境后,还是输入 end 命令回到 Stata 环境中,两个内存空间中的数据均不会因为切换内存空间而改变。

该调用切换环境的过程仅仅相当于我们打开或关上 「Mata 房间」 或 「stata 房间」 的 「门」 !只有在房间内部的命令才会影响房间内的数据,而开\关门这一动作并没有理由也不会改变数据。

演示如下:

. disp str1 
I love lianxh.
. disp numb1
666888

. mata
------------------------------------------
: str2
  I love lianxh, too!
: numb2
  888666
: end
------------------------------------------

2. 数据交互

数据类型由「组织类别 (organizational type)」和「元素类别 (element type)」构成。常见的组织类别包括:标量 (scalar) 、矩阵 (matrix) 、向量 (vector) ;常见的元素类别包括实数 (real) 、字符串 (string) 。本节将介绍常见数据类型在 Stata 与 Mata 之间的输入与输出。

注意:在使用 Mata 的函数时,调用对象必须用引号,而在 Stata 环境下调用对象通常无需用引号。具体区别可见下例。

2.1 数值型标量 (real scalar)

2.1.1 Stata → Mata

对于 「Stata 房间」 中的数值型标量,我们可以在 Mata 环境下使用 st_numscalar 命令将其拷贝到 「Mata 房间」 。

  • st_numscalar("name") 将在 「Mata 房间」 中生成数值型标量 name,取值与 「Stata 房间」 中数值型标量 name 相同
  • st_numscalar("name",value) 将设定或改变 「Stata 房间」 中数值型标量 name 的值为 value
. scalar a = 888888

. mata
------------------------------------------
: st_numscalar("a")
  888888
: st_numscalar("a",666666)
: end
------------------------------------------

. display a
666666

2.1.2 Mata → Stata

对于 「Mata 房间」 中的数值型标量,我们可以在 Mata 环境下使用 st_numscalar 命令将其拷贝到 「Stata 房间」 。

  • st_numscalar("name",name) 将在 「Stata 房间」 中生成存储着数值型标量 name,取值与 「Mata 房间」 中数值型标量 name 相同
. mata
------------------------------------------
: b = 8888
: st_numscalar("b",b)
: end
------------------------------------------

. display b
8888

2.2 字符串型标量 (string scalar)

2.2.1 从 Stata 到 Mata

  • st_strscalar("name") 将在 「Mata 房间」 中生成字符串型标量 name,取值与 「Stata 房间」 中数值型标量 name 相同
  • st_numscalar("name",value) 将设定或改变 「Stata 房间」 中字符串型标量 name 的值为 value
. scalar c = "I love lianxh."

. mata
------------------------------------------
: st_strscalar("c")
  I love lianxh.
: st_strscalar("c","I love lianxh, too!")
: end
------------------------------------------

. display c
I love lianxh, too!

2.2.2 从 Mata 到 Stata

  • st_strscalar("name",name) 将在 「Stata 房间」 中生成字符串型标量 name,取值与 「Mata 房间」 中字符串型标量 name 相同
. mata
------------------------------------------
: d = "I deeply love lianxh."
: st_strscalar("d",d)
: end
------------------------------------------

. display d
I deeply love lianxh.

2.3 实数矩阵 (real matrix)

2.3.1 从 Stata 到 Mata

  • st_matrix(name) 将在 「Mata 房间」 中生成矩阵 name,取值与 「Stata 房间」 中矩阵 name 相同
. matrix e = (5,1\8,8)
. matrix list e
e[2,2]
    c1  c2
r1   5   1
r2   8   8

. mata
------------------------------------------
: st_matrix("e")
       1   2
    +---------+
  1 |  5   1  |
  2 |  8   8  |
    +---------+
: end
------------------------------------------

2.3.2 从 Mata 到 Stata

  • st_matrix("name",name) 将在 「Stata 房间」 中生成矩阵 name,取值与 「Mata 房间」 中矩阵 name 相同
. mata
------------------------------------------
: f = (5,1\6,6)
: f
       1   2
    +---------+
  1 |  5   1  |
  2 |  6   6  |
    +---------+
: st_matrix("f",f)
: end
------------------------------------------

. matrix list f
f[2,2]
    c1  c2
r1   5   1
r2   6   6

2.4 变量交互 (variable)

我们可以将 Stata 中的所有变量视为一个 行数 为观测样本数 (obs) × 列数 为变量个数 (k) 的矩阵。因而与 Mata 的交互过程可以视为对该矩阵进行分列(提取单个变量作为 列向量)、分块(提取多个变量组成一个 子矩阵)操作。反之则是将 Mata 中矩阵的多个列向量转换为 Stata 中 变量 数据类型。

2.4.1 导入 Mata :st_view() 和 st_data()

2.4.1.1 函数语法

将 Stata 中的 变量 导入 Mata 并生成矩阵,主要用 Mata 环境下的这两个函数 st_view()st_data(),语法如下:

(鄙人写法与 help 文档中不同,但有助于读者理解,并且效果一致)

  • st_data(i, j)
  • st_view(matname, i, j)

其中,

  • i 表示选取的 行数,如 i=1 代表取第一行,i=(1,3) 代表取 第一到第三 行,i=. 代表选取所有行(即所有观测值)
  • j 代表选取的 列数,如 j=1 代表取第一列,j=(1,3) 代表取 第一和第三 列,j=. 代表选取所有列(即所有变量)
  • 此外,j 可以为变量名称,如 j="v1" 代表取变量 v1 这一列,j=("v1","v3") 代表取 v1 和 v3 这两列
  • matname 表示新生成的矩阵的名称

2.4.1.2 st_data() 操作实例

首先,我们生成一个包含 6 个变量(v1-v6),每个变量包含 6 个观测值的数据集:

set obs 6			//设定观测值为6个
set seed 888888		//设定一个美好的种子数,利于复现
forvalues i=1/6 {	//该数据集包含v1-v6共6个变量,每个变量有6个观测值
	gen d`i' = 100*uniform()	//生成(0,100)的随机数
	gen v`i'=int(d`i')		    //取整数
	drop d`i'
}

生成结果如下

. list v1-v6, clean noobs
v1   v2   v3   v4   v5   v6  
52   18   76   77    7   70  
78   52   15   42    8   50  
47   36   45   58   33   74  
60   81   91   56   54   61  
47   39   49   56   98   41  
83   37   98   77   42   21  

其次,我们在 Mata 环境下举例说明:

生成包含所有变量的矩阵 m1

. mata
------------------------------------------
: m1 = st_data(.,.)
: m1
        1    2    3    4    5    6
    +-------------------------------+
  1 |  52   18   76   77    7   70  |
  2 |  78   52   15   42    8   50  |
  3 |  47   36   45   58   33   74  |
  4 |  60   81   91   56   54   61  |
  5 |  47   39   49   56   98   41  |
  6 |  83   37   98   77   42   21  |
    +-------------------------------+

生成包含所有变量第一个观测值的行向量 m2

: m2 = st_data(1,.)
: m2
        1    2    3    4    5    6
    +-------------------------------+
  1 |  52   18   76   77    7   70  |
    +-------------------------------+

生成包含第一个变量所有观测值的列向量 m3

: m3 = st_data(.,1)
: m3
        1
    +------+
  1 |  52  |
  2 |  78  |
  3 |  47  |
  4 |  60  |
  5 |  47  |
  6 |  83  |
    +------+

生成包含所有变量第一到第三个观测值的矩阵 m4

: m4 = st_data((1,3),.)
: m4
        1    2    3    4    5    6
    +-------------------------------+
  1 |  52   18   76   77    7   70  |
  2 |  78   52   15   42    8   50  |
  3 |  47   36   45   58   33   74  |
    +-------------------------------+

生成包含第一个变量和第三个变量所有观测值的矩阵 m5

: m5 = st_data(.,(1,3))
: m5
        1    2
    +-----------+
  1 |  52   76  |
  2 |  78   15  |
  3 |  47   45  |
  4 |  60   91  |
  5 |  47   49  |
  6 |  83   98  |
    +-----------+

生成包含第一个变量和第三个变量的第一到第三个观测值的矩阵 m6

: m6 = st_data((1,3),(1,3))
: m6
        1    2
    +-----------+
  1 |  52   76  |
  2 |  78   15  |
  3 |  47   45  |
    +-----------+

生成包含变量 v1 所有观测值的列向量

: m7 = st_data(.,"v1 ")
: m7
        1
    +------+
  1 |  52  |
  2 |  78  |
  3 |  47  |
  4 |  60  |
  5 |  47  |
  6 |  83  |
    +------+

生成包含变量 v1 和 v3 所有观测值的矩阵

: m8 = st_data(.,("v1","v3"))
: m8
        1    2
    +-----------+
  1 |  52   76  |
  2 |  78   15  |
  3 |  47   45  |
  4 |  60   91  |
  5 |  47   49  |
  6 |  83   98  |
    +-----------+
: end
------------------------------------------

注意:行反映观测值范围,列只反映变量具体位置。即 i=(1,3) 代表第一到第三个观测值,而 j=(1,3) 表示的是第一个变量和第三个变量。

2.4.1.3 st_view() 操作实例

因为st_view()st_data()语法相近,本节直接展示命令与结果。

生成空矩阵待命

. mata
------------------------------------------
: mm1 = mm2 = mm3 = mm4 = mm5 = mm6 = mm7 = mm8 =.

生成包含所有变量的矩阵 mm1

: st_view(mm1,.,.)                                                                                                        //生成包含所有变量的矩阵m1
: mm1
        1    2    3    4    5    6
    +-------------------------------+
  1 |  52   18   76   77    7   70  |
  2 |  78   52   15   42    8   50  |
  3 |  47   36   45   58   33   74  |
  4 |  60   81   91   56   54   61  |
  5 |  47   39   49   56   98   41  |
  6 |  83   37   98   77   42   21  |
    +-------------------------------+

生成包含所有变量第一个观测值的行向量 mm2

: st_view(mm2,1,.)
: mm2
        1    2    3    4    5    6
    +-------------------------------+
  1 |  52   18   76   77    7   70  |
    +-------------------------------+

生成包含第一个变量所有观测值的列向量 mm3

: st_view(mm3,.,1)
: mm3
        1
    +------+
  1 |  52  |
  2 |  78  |
  3 |  47  |
  4 |  60  |
  5 |  47  |
  6 |  83  |
    +------+

生成包含所有变量第一到第三个观测值的矩阵 mm4

: st_view(mm4,(1,3),.)
: mm4
        1    2    3    4    5    6
    +-------------------------------+
  1 |  52   18   76   77    7   70  |
  2 |  78   52   15   42    8   50  |
  3 |  47   36   45   58   33   74  |
    +-------------------------------+

生成包含第一个变量和第三个变量所有观测值的矩阵 mm5

: st_view(mm5,.,(1,3))
: mm5
        1    2
    +-----------+
  1 |  52   76  |
  2 |  78   15  |
  3 |  47   45  |
  4 |  60   91  |
  5 |  47   49  |
  6 |  83   98  |
    +-----------+

生成包含第一个变量和第三个变量的第一到第三个观测值的矩阵 mm6

: st_view(mm6,(1,3),(1,3))
: mm6
        1    2
    +-----------+
  1 |  52   76  |
  2 |  78   15  |
  3 |  47   45  |
    +-----------+

生成包含变量 v1 所有观测值的列向量 mm7

: st_view(mm7,.,"v1 ")
: mm7
        1
    +------+
  1 |  52  |
  2 |  78  |
  3 |  47  |
  4 |  60  |
  5 |  47  |
  6 |  83  |
    +------+

生成包含变量 v1 和 v3 所有观测值的矩阵 mm8

: st_view(mm8,.,("v1","v3"))
: mm8
        1    2
    +-----------+
  1 |  52   76  |
  2 |  78   15  |
  3 |  47   45  |
  4 |  60   91  |
  5 |  47   49  |
  6 |  83   98  |
    +-----------+
: end
------------------------------------------

2.4.1.4 st_data() 与 st_view() 的区别

  • st_data() 是将 「Stata 房间」 中的变量复制生成新的矩阵后存储在 「Mata 房间」 之中,新生成的矩阵与原有的变量完全独立。而 st_view() 则是以矩阵的方式来查看和处理 「Stata 房间」 中的变量,两者联系紧密。

  • st_data() 生成的矩阵需要对等大小的内存空间予以储存,而 st_view() 链接到的矩阵只占用极少的内存。

  • 对于 st_view() 函数,变量与矩阵之间存在联动,即修改任何一方都会影响另一方。而 st_data() 函数能保证二者完全独立,互不干涉。具体如下:

    一、st_data()

    st_data()是将 「Stata 房间」 中的变量复制生成新的矩阵后存储在 「Mata 房间」 之中,新生成的矩阵与原有的变量完全独立。

. mata
------------------------------------------
: m1[1,1]= 8888                                                                                                                   //更改矩阵m1中第一行第一列的元素为8888
: m1[2,1]= 88888                                                                                                          //更改矩阵m1中第二行第一列的元素为88888
: end
------------------------------------------
. list v1 in 1/5
     +----+
     | v1 |
     |----|
  1. | 52 |
  2. | 78 |
  3. | 47 |
  4. | 60 |
  5. | 47 |
     +----+

我们清楚地看到变量 v1 的第一和第二个观测值并未发生改变。

二、st_view()

. mata
------------------------------------------
: mm1[1,1]=8888                                                                                                                   //更改矩阵mm1中第一行第一列的元素为8888
: mm1[2,1]=88888                                                                                                          //更改矩阵mm1中第二行第一列的元素为88888
: end
------------------------------------------
. list v1 in 1/5
     +-------+
     |    v1 |
     |-------|
  1. |  8888 |
  2. | 88888 |
  3. |    47 |
  4. |    60 |
  5. |    47 |
     +-------+

我们清楚地看到变量 v1 的第一和第二个观测值已经发生改变。

2.4.2 导回 Stata :st_store()st_addvar

因为使用 st_store()st_addvar 将矩阵转换为变量较为繁琐,推荐使用 2.4.4 节中的 getmata() 函数。

2.4.1.2 函数语法

将 Mata 中的 矩阵 导回 Stata 并生成变量,主要用 Mata 环境下的这两个函数 st_store()st_addvar(),语法如下:

(鄙人写法与 help 文档中不同,但有助于读者理解,并且效果一致)

  • st_store(i , j , x) 用于改变 Stata 中现有变量的值
  • st_addvar(type, name) 用于添加 Stata 中的变量

其中 i 代表选取的 行数,如 i=1 代表取第一行,i=(1,3) 代表取 第一到第三 行,i=. 代表选取所有行(即所有观测值)

其中 j 代表选取的 列数,如 j=1 代表取第一列,j=(1,3) 代表取 第一和第三 列,j=. 代表选取所有列(即所有变量)

其中 x 代表用于更改的数值,可以是单个数值,也可以是列向量或行向量或矩阵

其中 j 可以为变量名称,如 j="v1" 代表取变量 v1 这一列,j=("v1","v3") 代表取 v1 和 v3 这两列

其中 type 为数据类型,如"byte" , "int" , "long" , "float" , "double" , "strL"

2.4.1.2 操作实例

首先,我们生成一个包含 6 个变量(v1-v6),每个变量包含 6 个观测值的数据集

set obs 6									//设定观测值为6个
set seed 888888						//设定一个美好的种子数,利于复现
forvalues i=1/6 {					//该数据集包含v1-v6共6个变量,每个变量有6个观测值
	gen d`i' = 100*uniform()				//生成(0,100)的随机数
	gen v`i'=int(d`i')	//取整数
	drop d`i'
}

生成结果如下

. list v1-v6, clean noobs
v1   v2   v3   v4   v5   v6  
52   18   76   77    7   70  
78   52   15   42    8   50  
47   36   45   58   33   74  
60   81   91   56   54   61  
47   39   49   56   98   41  
83   37   98   77   42   21  

其次,我们在 Mata 环境下举例说明:

. clear mata
. mata:
------------------------------------------
: g = st_data(.,"v3")
//在 Mata 中生成存有变量v3值的列向量g
: g
        1
    +------+
  1 |  76  |
  2 |  15  |
  3 |  45  |
  4 |  91  |
  5 |  49  |
  6 |  98  |
    +------+
: st_store(., st_addvar("float","newv3"),g)
//将列向量g的所有观测值导入成变量,命名为newv3
: end
-------------------------------------------

. list newv3 in 1/6
//成功将 Mata 中矩阵导回成 Stata 中的变量
     +-------+
     | newv3 |
     |-------|
  1. |    76 |
  2. |    15 |
  3. |    45 |
  4. |    91 |
  5. |    49 |
     |-------|
  6. |    98 |
     +-------+

2.4.3 导入 Mata :putmata()

Stata12.0更新加入了 putmata()getmata()命令专门用于 Stata 中变量和 Mata 中矩阵之间的转换,语法简洁,功能丰富。

putmata() 用于根据 Stata 中的变量生成 Mata 中的矩阵。

语法如下:

putmata putlist [if] [in] [, putmata_options]
  • putmata_options 包括:

    • omitmissing :省略有缺失的观测值
    • view :通过 view 的方式创建向量和矩阵(参考 2.4.1 导入 Mata :st_view() st_data()
    • replace :替换现有的向量和矩阵
  • putlist 包括:

*
varname
varlist
vecname=varname
matname=(varlist)
matname=([varlist] # [varlist] [...])

举例说明:

导入自带的 auto.dta 数据集

clear
sysuse auto.dta

在 Mata 中为内存中的每个 Stata 变量创建一个向量。向量包含与 Stata 变量相同的数据。向量与相应变量的名称相同。

putmata *

在 Mata 中为每个指定的变量创建一个向量。向量与相应变量的名称相同。

putmata mpg weight displ

在 Mata 中为每个指定的变量创建一个向量。向量可以自由命名。

putmata mileage=mpg pounds=weight

在 Mata 中为指定的变量创建一个向量,也可以创建一个矩阵包含多个变量。

putmata y=mpg X=(weight displ)

更多用法详见 help putmata

2.4.4 导回 Stata :getmata()

getmata() 用于根据 Mata 中的矩阵生成 Stata 中的变量

getmata getlist [, getmata_options]
  • getmata_options 包括:

  • update 更新现有变量

  • replace 替换现有的变量

  • id(name) 根据变量名和矩阵名的相等值将观察值与之匹配

  • force 允许矩阵行数与变量观测值不同时强行转换

  • getlist 包括:

vecname
varname=vecname
(varname varname ... varname)=matname
(varname*)=matname

举例说明:

为每个指定的 Mata 向量创建一个 Stata 变量,且变量的名称与对应的向量,另外名称也不能缩写。

getmata x1 x2

为每个指定的 Mata 向量创建一个 Stata 变量。变量名将与对应的矢量名称。

getmata myvar1=x1 myvar2=x2

创建 Stata 变量,对应于指定的 Mata 矩阵的每一列。如果矩阵有两列,相应的变量将命名为 firstvarsecondvar 。如果矩阵 有三列,那么依次指定三个变量名。

getmata (firstvar secondvar)=X

创建 Stata 变量,对应于指定的 Mata 矩阵的每一列。变量将命名为 myvar1、myvar2 等。

getmata (myvar*)=X

更多用法详见 help putmata

3. 命令交互

3.1 主要使用 Mata 时的交互

当我们需要长时间大范围使用 Mata 环境时,我们需要输入 matamata: 进入该环境,并且在结束或转回 Stata 时,需要输入 end 进行声明。

注意: Mata 和 mata: 的区别在于:当我们的程序运行出错时,mata: 之下程序会报错并退回到 Stata 环境中,而 Mata 之下程序只会报错但仍然会留在 Mata 环境中。

当我们需要在 Mata 环境中使用 Stata 命令时,我们只需要在 Stata 命令前输入 mata stata 即可。例如:

. mata
-------- mata (type end to exit) ----------
: mata stata sysuse auto.dta
(1978 Automobile Data)
: mata stata list mpg in 1/10
     +-----+
     | mpg |
     |-----|
  1. |  22 |
  2. |  17 |
  3. |  22 |
  4. |  20 |
  5. |  15 |
     |-----|
  6. |  18 |
  7. |  26 |
  8. |  20 |
  9. |  16 |
 10. |  19 |
     +-----+
: end
-------------------------------------------

3.2 主要使用 Stata 时的交互

当我们需要在 Stata 环境中使用 Mata 命令时,我们只需要在 Mata 命令前输入mata:,即可。例如:

. clear
. sysuse auto.dta
(1978 Automobile Data)
. mata: m1 = st_data(.,.)

end of do-file

方法: 固定效应模型、FM 估计、动态面板、稳健性检验、衡量偏误问题
→ 直接听课
→ 课件展示https://gitee.com/arlionn/paper101

4. 程序交互

通常,我们一般在 do 和 ado 文件中嵌套使用 Mata 编写的程序,调用方法是在输入的函数名称前加上 mata: 。例如:

. stata commands
. mata: m_ols("varlist", "intercept")  //调用函数前输mata:
. stata commands

5. 本文涉及的 Stata 代码

使用建议: 可以复制到一个新建的 dofile 中,另存为 lianxh_mata.do,即可反复查看、练习。

//++++++++++++++++++++++
//1.为什么会存在交互问题
//++++++++++++++++++++++
	scalar str1 = "I love lianxh."
	scalar numb1 = 666888
	mata
	str2     = "I love lianxh, too!" 
	numb2    = 888666
	end
	display str1
	display numb1
	mata
	str2
	numb2
	end

//++++++++++++++++++++++
//2. 数据交互
//++++++++++++++++++++++

//=======================
//-2.1 数值型标量 (real scalar) 

    //2.1.1 从 Stata 到 Mata :
	scalar a = 888888
	mata
	st_numscalar("a")
	st_numscalar("a",666666)
	end
	display a		
  
    //2.1.2 从 Mata 到 Stata :		
	mata
	b = 8888
	st_numscalar("b",b)
	end
	display b

//=======================	
//-2.2 字符串型标量 (string scalar) 

    //2.2.1 从 Stata 到 Mata :
	scalar c = "I love lianxh." 
	mata
	st_strscalar("c")
	st_strscalar("c","I love lianxh, too!")
	end
	display c
   
    //2.2.2 从 Mata 到 Stata :		
	mata
	d = "I deeply love lianxh." 
	st_strscalar("d",d)
	end
	display d
	
//=======================    
//-2.3 实数矩阵 (real matrix) 

    //2.3.1 从 Stata 到 Mata :
	matrix e = (5,1\8,8)
	matrix list e
	mata
	st_matrix("e")
	end 
    
    //2.3.2 从 Mata 到 Stata :
	mata
	f = (5,1\6,6)
	f
	st_matrix("f",f)
	end
	matrix list f
	
//=======================    
//-2.4 变量交互 (variable) 

		//2.4.1 导入 Mata :`st_view()` `st_data()`
	//首先,生成一个数据集用于举例
	//该数据集包含v1-v6共6个变量,每个变量有6个观测值
	clear all
	set obs 6
	set seed 888888
	forvalues i=1/6 {			
		gen d`i' = 100*uniform()  //生成(0,100)的随机数
		gen v`i'=int(d`i') //取整数
		drop d`i'
	}
	list v1-v6, clean noobs
	//展示st_data()命令
	mata
	//生成包含所有变量的矩阵m1
	m1 = st_data(.,.)	
	m1
	//生成包含所有变量第一个观测值的行向量m2
	m2 = st_data(1,.)	
	m2
	//生成包含第一个变量所有观测值的列向量m3
	m3 = st_data(.,1)	
	m3
	//生成包含所有变量第一到第三个观测值的矩阵m4
	m4 = st_data((1,3),.)	
	m4
	//生成包含第一个变量和第三个变量所有观测值的矩阵m5
	m5 = st_data(.,(1,3))	
	m5
	//生成包含第一和第三个变量的第一到第三个观测值的矩阵m6
	m6 = st_data((1,3),(1,3))	
	m6
	//生成包含变量v1所有观测值的列向量
	m7 = st_data(.,"v1 ")	
	m7
	//生成包含变量v1和v3所有观测值的矩阵
	m8 = st_data(.,("v1","v3"))
	m8
	end
	//展示st_view()命令
	mata
	//生成空矩阵待命
	mm1 = mm2 = mm3 = mm4 = mm5 = mm6 = mm7 = mm8 =.
	//生成包含所有变量的矩阵mm1
	st_view(mm1,.,.)
	mm1
	//生成包含所有变量第一个观测值的行向量mm2
	st_view(mm2,1,.)	
	mm2
	//生成包含第一个变量所有观测值的列向量mm3
	st_view(mm3,.,1)	
	mm3
	//生成包含所有变量第一到第三个观测值的矩阵mm4
	st_view(mm4,(1,3),.)	
	mm4
	//生成包含第一个变量和第三个变量所有观测值的矩阵mm5
	st_view(mm5,.,(1,3))	
	mm5
	//生成包含第一和第三个变量的第一到第三个观测值的矩阵mm6
	st_view(mm6,(1,3),(1,3))	
	mm6
	//生成包含变量v1所有观测值的列向量mm7
	st_view(mm7,.,"v1 ")	
	mm7
	//生成包含变量v1和v3所有观测值的矩阵mm8
	st_view(mm8,.,("v1","v3"))
	mm8
	end
	//展示st_view()与st_data()的区别
	//一、st_data()
	//st_data()是将 「Stata房间」 中的变量复制生成
	//新的矩阵后存储在 「Mata房间」 之中,
	//新生成的矩阵与原有的变量完全独立。
	mata
	//更改矩阵m1中第一行第一列的元素为8888
	m1[1,1]= 8888
  //更改矩阵m1中第二行第一列的元素为88888
	m1[2,1]= 88888
	end
	list v1 in 1/5

	//二、st_view()
	//st_view()则是以矩阵的方式来查看和处理 
	//「Stata房间」 中的变量,两者存在联动,
	//即修改任何一方都会影响另一方
	mata
	//更改矩阵mm1中第一行第一列的元素为8888
	mm1[1,1]=8888		
	//更改矩阵mm1中第二行第一列的元素为88888
	mm1[2,1]=88888
	end
	list v1 in 1/5

		//2.4.2 导回 Stata :`st_store()` `st_addvar`
	clear
	//首先,生成一个数据集用于举例
	//该数据集包含v1-v6共6个变量,每个变量有6个观测值
	set obs 6
	set seed 888888
	forvalues i=1/6 {	
		gen d`i' = 100*uniform()
		gen v`i'=int(d`i')	//取整数
		drop d`i'																
	}
	clear mata
	mata:
	//在 Mata 中生成存有变量v3值的列向量g
	g = st_data(.,"v3")                			
	g							
  //将列向量g的所有观测值导入成变量,命名为newv3
	st_store(., st_addvar("float","newv3"),g) 
	end
	//成功将 Mata 中矩阵导回成 Stata 中的变量
	list newv3 in 1/6												  

		//2.4.3 导入 Mata :`putmata()`
	clear all
	sysuse auto.dta
	putmata *,replace
	putmata mpg weight displ,replace
	putmata mileage=mpg pounds=weight ,replace
	putmata y=mpg X=(weight displ) ,replace
	
		//2.4.4 导回 Stata :`getmata()`
	//命令类似putmata,详见help文档

//++++++++++++++++++++++
//3. 命令交互
//++++++++++++++++++++++

//=======================	
//-3.1 主要使用 Mata  时的交互 

	mata
	mata stata sysuse auto.dta
	mata stata list mpg in 1/10
	end
	
//=======================	
//-3.2 主要使用 Stata 时的交互

	clear
	sysuse auto.dta
	mata: m1 = st_data(.,.)	

//++++++++++++++++++++++
//4. 程序交互
//++++++++++++++++++++++

//=======================	
//-4.1 do 和 ado 文件中运行 Mata 程序

	/*
	stata commands
	mata:
	mata commands
	end
	stata commands
	*/

6. 总结

本文介绍了 st_numscalar st_strscalar st_matrix st_view st_data st_store st_addvar putmata getmata 等命令的使用。注意,除了 putmata getmata 命令是在 Stata 环境下执行的,其余命令均需在 Mata 环境下使用。有关上述命令的更多介绍详见 Stata 官方帮助文档。

7. 参考资料和相关推文

  • 专题:Stata程序
  • Ben Jann, 2019, Review of William Gould's The Mata Book: A Book for Serious Programmers and Those Who Want to Be, Stata Journal, 19(3): 734–737. -PDF-
  • Gould, William. 2018. The Mata Book. College Station, TX: Stata Press.
  • Baum, C. F. 2016. An Introduction to Stata Programming. 2nd ed. College Station, TX: Stata Press.
  • Buis, M. L. 2007. Stata tip 53: Where did my p-values go?. Stata Journal 7: 584–586.
  • Gould, William. 2005, Mata Matters: Translating Fortran, Stata Journal, 5(3): 421–441. -PDF-
  • Gould, William. 2005, Mata Matters: Using Views onto the Data, Stata Journal, 5(4): 567–573. -PDF-
  • Gould, William. 2006, Mata Matters: Creating New Variables—sounds Boring, isn't, Stata Journal, 6(1): 112–123. -PDF-
  • Gould, William. 2006, Mata Matters: Precision, Stata Journal, 6(4): 550–560. -PDF-
  • Gould, William. 2007, Mata Matters: Structures, Stata Journal, 7(4): 556–570. -PDF-
  • Gould, William. 2007, Mata Matters: Subscripting, Stata Journal, 7(1): 106–116. -PDF-
  • Gould, William. 2008, Mata Matters: Macros, Stata Journal, 8(3): 401–412. -PDF-
  • Gould, William. 2009, Mata Matters: File Processing, Stata Journal, 9(4): 599–620. -PDF-
  • Gould, William. 2010, Mata Matters: Stata in Mata, Stata Journal, 10(1): 125–142. -PDF-
  • Gould, William, Nicholas J. Cox, 2011, Stata Tip 100: Mata and the Case of the Missing Macros, Stata Journal, 11(2): 323–324. -PDF-
  • Henrik Støvring, 2007, A Generic Function Evaluator Implemented in Mata, Stata Journal, 7(4): 542–555. -PDF-
  • Matthew J. Baker, 2014, Adaptive Markov Chain Monte Carlo Sampling and Estimation in Mata, Stata Journal, 14(3): 623–661. -PDF-
  • Stanislav Kolenikov, 2012, Scrambled Halton Sequences in Mata, Stata Journal, 12(1): 29–44. -PDF-
  • Sylvain Weber, 2010, Bacon: An Effective way to Detect Outliers in Multivariate Data Using Stata (and Mata), Stata Journal, 10(3): 331–338. -PDF-

相关课程

连享会-直播课 上线了!
http://lianxh.duanshu.com

免费公开课:


课程一览

支持回看

专题 嘉宾 直播/回看视频
最新专题 因果推断, 空间计量,寒暑假班等
数据清洗系列 游万海 直播, 88 元,已上线
研究设计 连玉君 我的特斯拉-实证研究设计-幻灯片-
面板模型 连玉君 动态面板模型-幻灯片-
面板模型 连玉君 直击面板数据模型 [免费公开课,2小时]

Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。


关于我们

  • Stata连享会 由中山大学连玉君老师团队创办,定期分享实证分析经验。直播间 有很多视频课程,可以随时观看。
  • 连享会-主页知乎专栏,300+ 推文,实证分析不再抓狂。
  • 公众号关键词搜索/回复 功能已经上线。大家可以在公众号左下角点击键盘图标,输入简要关键词,以便快速呈现历史推文,获取工具软件和数据下载。常见关键词:课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法

连享会主页  lianxh.cn
连享会主页 lianxh.cn

连享会小程序:扫一扫,看推文,看视频……

扫码加入连享会微信群,提问交流更方便

✏ 连享会学习群-常见问题解答汇总:
https://gitee.com/arlionn/WD

New! lianxh 命令发布了:
随时搜索连享会推文、Stata 资源,安装命令如下:
. ssc install lianxh
使用详情参见帮助文件 (有惊喜):
. help lianxh