☰
Stata矩阵计算入门:从matrix命令到计量经济学实战
2026/10/14 1:34:09 网站建设 项目流程

1. 为什么矩阵计算是Stata进阶路上绕不开的坎

很多人学Stata是从reg、sum、tab这几个命令开始的,跑个回归、做个描述性统计,感觉已经够用了。但只要你稍微往计量经济学深处走一步,比如做工具变量法的矩阵推导、自己写GMM估计量、实现空间权重矩阵的运算,或者单纯想搞懂matrix list e(b)里那一堆数字到底怎么来的,矩阵计算就是那道必须跨过去的门槛。

我刚开始接触Stata矩阵的时候,最大的困惑不是数学本身,而是“为什么Stata要有两套矩阵系统”。一套是matrix开头的传统矩阵命令,另一套是mata——一个完整的矩阵编程语言。这个问题困扰了我很久,后来才慢慢理解:matrix命令是给交互式操作和简单运算用的,语法直观、上手快;而mata是给复杂算法和性能敏感场景用的,功能强大但学习曲线陡。对于小白来说,先把matrix这一套吃透,覆盖80%的日常需求完全没问题。

这篇汇总就是把我自己从零开始踩过的坑、查过的文档、反复试过的命令,按操作逻辑重新整理一遍。不追求大而全,而是把最常用的矩阵创建、赋值、运算、提取、存储这几个环节讲清楚。每个命令我都会说明“为什么这么写”“什么时候用”“哪里容易出错”。如果你正在学Stata的矩阵操作,或者被某个矩阵报错卡住了,这篇内容应该能帮你省下不少翻文档的时间。

2. Stata矩阵操作的核心逻辑与基础准备

2.1 传统matrix命令与mata的分工逻辑

Stata里做矩阵运算有两条路。第一条是matrix系列命令,比如matrix define、matrix list、matrix A = B * C,语法接近线性代数的书写习惯,适合做小规模的矩阵定义、基本运算和结果提取。第二条是mata,它是一个嵌入在Stata里的矩阵编程环境,支持函数、循环、条件判断,适合写自定义估计量、做大规模数值计算。

为什么要有两套?我个人的理解是:matrix命令的设计目标是“让用户用最少的代码完成常见的矩阵操作”,所以它牺牲了一部分灵活性,换来了语法的简洁。比如你想定义一个3×3的矩阵,matrix命令一行就能搞定;但在mata里,你需要先进入mata环境,再写A = (1,2,3 \ 4,5,6 \ 7,8,9),虽然也不复杂,但多了一层环境切换。

对于小白来说,建议先把matrix命令用熟。原因很简单:Stata的很多官方命令和用户写的外部命令,在存储结果时用的都是matrix格式。比如e(b)存储回归系数向量,e(V)存储方差-协方差矩阵,r(table)存储描述性统计的结果矩阵。你不需要会写复杂的矩阵程序,但你必须会从这些结果矩阵里提取你想要的数字。这是矩阵计算最基础、最高频的应用场景。

2.2 矩阵的创建与赋值:从零开始搭建你的第一个矩阵

创建矩阵最直接的方式是用matrix define命令,简写为matrix。基本语法是:

matrix matrix_name = (row1 \ row2 \ row3)

反斜杠\表示换行,逗号表示同一行内不同列的分隔。比如定义一个2×3的矩阵:

matrix A = (1, 2, 3 \ 4, 5, 6) matrix list A

运行后你会看到:

A[2,3] c1 c2 c3 r1 1 2 3 r2 4 5 6

这里有几个细节值得注意。第一,矩阵名不能和已有的标量、变量名冲突,否则Stata会报错。我习惯用大写字母开头命名矩阵,比如A、B、X,这样一眼就能和变量名区分开。第二,矩阵元素可以是表达式,比如matrix B = (1+2, 3*4 \ 5/2, 6^2),Stata会先计算再存储。第三,如果矩阵元素来自已有的标量或矩阵,可以直接引用,比如matrix C = (A[1,1], A[2,2] \ A[1,3], A[2,1])。

还有一种常见的创建方式是从变量生成矩阵。比如你想把数据集里某几个变量的观测值变成一个矩阵,可以用mkmat命令:

mkmat var1 var2 var3, matrix(X)

这个命令会把var1到var3的所有观测值按行堆叠成矩阵X。如果只想保留满足条件的观测,可以先keep if或者加if条件。mkmat的一个坑是:它默认把缺失值也放进去,如果数据里有缺失值,后续矩阵运算会出问题。所以用之前最好先检查一下缺失情况,或者加if !missing(var1, var2, var3)。

2.3 矩阵的索引与元素提取:怎么从大矩阵里精准拿数

矩阵建好之后,最常见的操作就是提取某个元素、某一行或某一列。Stata的索引语法和大多数编程语言类似,用方括号加行列号:

matrix A = (1, 2, 3 \ 4, 5, 6) display A[1,2] // 显示第一行第二列的元素,结果是2 display A[2,1] // 显示第二行第一列的元素,结果是4

提取整行或整列用A[1,.]和A[.,1],但要注意,这样提取出来的是一个1×3或2×1的矩阵,不能直接当标量用。如果你想把提取出来的矩阵再赋值给一个新矩阵,可以:

matrix row1 = A[1,.] matrix col2 = A[.,2]

这里有个我踩过的坑:matrix命令在赋值时,如果右边是一个矩阵表达式,左边会自动匹配维度。但如果你写matrix row1 = A[1,1],Stata会创建一个1×1的矩阵,而不是标量。标量和1×1矩阵在Stata里是两种不同的对象,很多命令对两者的处理方式不同。比如display可以显示标量,但显示1×1矩阵需要用matrix list。

另外,Stata的矩阵索引是从1开始的,不是0。这一点和Python、C等语言不同,刚开始容易搞混。我建议在写循环的时候特别注意,比如forvalues i = 1/3对应的是第1行到第3行,而不是第0行到第2行。

3. 矩阵基本运算的实操要点与避坑指南

3.1 加法、减法与数乘:维度匹配是第一原则

矩阵加减法的语法很直观:

matrix A = (1, 2 \ 3, 4) matrix B = (5, 6 \ 7, 8) matrix C = A + B matrix D = A - B matrix E = 2 * A

但这里有一个硬性约束:两个矩阵相加或相减,它们的维度必须完全相同。如果A是2×2,B是2×3,Stata会直接报错“conformability error”。这个错误信息在矩阵运算里非常常见,意思是“维度不匹配,无法运算”。我刚开始的时候经常被这个报错搞得一头雾水,后来养成了一个习惯:每次做矩阵运算之前,先用matrix list或者display rowsof(A), colsof(A)确认一下维度。

数乘没有维度限制,一个标量可以乘任意维度的矩阵。但要注意,Stata里标量和矩阵的乘法顺序不影响结果,2*A和A*2是等价的。不过如果是两个矩阵相乘,顺序就至关重要了。

3.2 矩阵乘法:内维相等才能乘,顺序不能反

矩阵乘法的语法是matrix C = A * B。这里的要求是:A的列数必须等于B的行数。比如A是2×3,B是3×4,那么C就是2×4。如果A是2×3,B是2×4,就会报conformability error。

我见过很多新手在这里犯错,包括我自己。有一次我想计算X'X,X是100×5的矩阵,我写了matrix XX = X * X',结果报错。原因是我把顺序搞反了:X * X'是100×100的矩阵,而X' * X才是5×5的矩阵。正确的写法是:

matrix XX = X' * X

这里'表示转置。转置操作在Stata里用单引号表示,比如A'就是A的转置。转置不改变矩阵的元素,只改变行列位置。一个m×n的矩阵转置后变成n×m。

矩阵乘法还有一个重要性质:不满足交换律。也就是说,A * B和B * A通常不相等,甚至可能一个能算、另一个报错。所以在写矩阵乘法的时候,一定要先想清楚你要的结果是什么维度,然后确定乘法的顺序。

3.3 转置、逆矩阵与行列式:进阶运算的三大件

转置的语法前面说了,用单引号。逆矩阵用invsym或者inv命令:

matrix A = (4, 7 \ 2, 6) matrix Ainv = invsym(A) matrix list Ainv

invsym计算的是对称逆矩阵,适用于对称正定矩阵;inv计算的是普通逆矩阵。对于大多数计量经济学里的矩阵,比如X'X,它是对称正定的,用invsym更高效也更稳定。如果矩阵不可逆,Stata会报错“matrix is singular”,意思是矩阵奇异,行列式为0。

行列式用det命令:

display det(A)

行列式的一个重要用途是判断矩阵是否可逆:如果行列式为0,矩阵不可逆。但在数值计算中,即使行列式不为0,如果它非常接近0,矩阵也可能是“病态”的,求逆结果会很不稳定。这时候可以考虑用invsym的广义逆功能,或者对矩阵做正则化处理。

我个人的经验是:在Stata里做矩阵求逆,尽量用invsym而不是inv,因为前者利用了对称性,数值稳定性更好。另外,如果矩阵维度很大(比如超过1000×1000),求逆会非常耗时,这时候要考虑是否有必要真的求逆,或者能不能用求解线性方程组的方式替代。

4. 矩阵结果的存储、调用与常见报错处理

4.1 把矩阵存进e()和r():结果提取的标准姿势

Stata的很多命令在运行后会把结果存储在e()或r()里。比如跑完回归reg y x1 x2,系数向量存在e(b),方差-协方差矩阵存在e(V)。你可以直接用matrix list e(b)查看,也可以把它们提取出来做进一步运算:

reg y x1 x2 matrix b = e(b) matrix V = e(V) matrix se = sqrt(diagonal(V))

这里diagonal(V)提取V的对角线元素组成列向量,sqrt对每个元素开方,得到标准误。这个操作在手动计算t统计量、置信区间的时候非常有用。

r()类结果类似,比如summarize之后,r(mean)、r(sd)、r(N)分别存储均值、标准差和样本量。但要注意,r()里存的是标量,不是矩阵。如果你想把这些标量拼成一个矩阵,可以:

summarize x1 scalar m1 = r(mean) summarize x2 scalar m2 = r(mean) matrix M = (m1 \ m2)

这里scalar定义的是标量,matrix定义的是矩阵。标量可以直接参与矩阵运算,Stata会自动把它当作1×1矩阵处理。

4.2 常见报错速查与排查思路

矩阵操作里最常见的报错就那么几个,我整理了一个速查表:

报错信息含义排查思路
conformability error维度不匹配用rowsof()和colsof()检查两个矩阵的维度
matrix is singular矩阵奇异,不可逆检查行列式是否为0,或是否有完全共线的行/列
matrix not found矩阵未定义确认矩阵名拼写正确,或先用matrix define创建
invalid matrix name矩阵名非法矩阵名不能以数字开头,不能与已有变量重名
type mismatch类型不匹配检查是标量还是矩阵,两者不能直接混用

我遇到最多的是conformability error和matrix is singular。前者通常是乘法顺序写反了,后者通常是数据里有完全共线的变量,或者样本量小于变量数导致X'X不满秩。

4.3 矩阵的保存与导出:怎么把结果带出Stata

矩阵算完之后,你可能想把它保存下来,或者导出到Excel里。保存矩阵用matrix save:

matrix save A using mymatrix.mmat

下次用的时候matrix load回来就行。导出到Excel可以用putexcel命令:

matrix list A putexcel set myresult.xlsx, replace putexcel A1 = matrix(A)

putexcel是Stata 13以后自带的命令,不需要额外安装。如果矩阵很大,导出可能会比较慢,建议先matrix list确认一下内容,避免导出不必要的东西。

还有一个技巧:如果你想把多个矩阵拼成一个大矩阵再导出,可以用matrix A = (B \ C)纵向拼接,或者matrix A = (B, C)横向拼接。但要注意维度匹配,纵向拼接要求列数相同,横向拼接要求行数相同。

5. 矩阵计算中的独家经验与进阶建议

5.1 我踩过的三个典型坑

第一个坑是矩阵名冲突。有一次我定义了一个矩阵叫X,后来跑回归的时候Stata报错说X已经存在。原来Stata的回归命令内部也会用X作为临时矩阵名,虽然理论上命名空间是隔离的,但在某些版本里确实会冲突。从那以后我养成了一个习惯:自定义矩阵一律用大写字母加下划线,比如X_MAT、BETA_VEC,避免和Stata内部命名撞车。

第二个坑是忘记清空矩阵。Stata里的矩阵一旦定义,就会一直留在内存里,直到你matrix drop或者关闭Stata。如果在一个循环里反复定义同名矩阵,后面的会覆盖前面的,但如果你以为它在累加,就会得到错误结果。我建议在循环开始前先matrix drop _all清空所有矩阵,或者用capture matrix drop matrix_name安全删除。

第三个坑是数值精度问题。Stata默认用双精度存储矩阵元素,但显示的时候只显示前几位。有时候你看到两个矩阵“相等”,实际上差了一个很小的数。做条件判断的时候,不要用==直接比较浮点数,而是用abs(A-B) < 1e-10这样的容差判断。

5.2 从matrix到mata:什么时候该升级

如果你发现自己需要写循环来做矩阵运算,或者需要自定义函数,那就是时候学mata了。matrix命令不支持循环,你只能一行一行写,或者用forvalues配合matrix命令反复定义。但mata里可以写for循环、while循环,可以定义函数,可以做递归。

举个例子,用matrix命令计算矩阵的幂,你只能手动乘:

matrix A2 = A * A matrix A3 = A2 * A

但在mata里,你可以写一个循环:

A = (1,2 \ 3,4) An = I(2) for (i=1; i<=10; i++) { An = An * A } An

这段代码计算A的10次方。I(2)是2×2的单位矩阵。mata的语法更接近C语言,但矩阵运算的写法更自然。

不过我的建议是:不要为了用mata而用mata。如果你的需求用matrix命令能解决,就用matrix,因为代码更短、更易读。只有当matrix命令明显不够用的时候,再切换到mata。

5.3 矩阵计算在计量经济学中的典型应用场景

矩阵计算在计量里最典型的应用就是OLS的矩阵形式。OLS估计量是b = (X'X)^(-1) X'y,用Stata矩阵命令写出来就是:

matrix X = ... matrix y = ... matrix XX = X' * X matrix XY = X' * y matrix b = invsym(XX) * XY

这个计算过程可以帮助你理解reg命令背后到底做了什么。你还可以手动计算标准误、t统计量、R方,和reg的输出对比,验证自己的理解是否正确。

另一个场景是工具变量法。2SLS的矩阵形式是b = (Z'X)^(-1) Z'y,其中Z是工具变量矩阵。用矩阵命令实现一遍,你对工具变量法的理解会深刻很多。

还有一个场景是面板数据的固定效应估计。组内变换可以用矩阵投影来实现,虽然Stata有xtreg命令,但自己用矩阵算一遍,能帮你理解固定效应到底在做什么。

6. 矩阵计算学习路径与资源建议

6.1 小白的学习顺序建议

如果你是完全零基础,我建议按这个顺序来:先学matrix define和matrix list,把矩阵的创建和查看搞熟;然后学索引和提取,知道怎么从矩阵里拿数;接着学加减乘和转置,这是最常用的运算;再学求逆和行列式,这是进阶运算;最后学从e()和r()里提取结果,这是实际应用中最频繁的操作。

不要一上来就啃mata,也不要一上来就试图理解所有矩阵运算的数学原理。先会用,再理解。很多概念比如“为什么X'X是对称的”“为什么invsym比inv稳定”,等你用多了、遇到问题了,自然就会去查、去理解。

6.2 我常用的查文档和调试方法

Stata自带的帮助文件是最好的学习资源。help matrix会列出所有矩阵命令的语法和示例。help mata是mata的入口。我建议把help matrix从头到尾看一遍,不用记住所有细节,但要知道有哪些命令可用。

调试矩阵代码的时候,我习惯在每一步之后加matrix list,确认中间结果是对的。比如:

matrix A = (1,2 \ 3,4) matrix list A matrix B = A' * A matrix list B matrix C = invsym(B) matrix list C

这样如果某一步出错,你能立刻定位到是哪一步的问题。另外,display rowsof(A)和display colsof(A)可以快速查看维度,比matrix list更简洁。

还有一个技巧是用capture命令捕获错误。比如:

capture matrix C = A * B if _rc != 0 { display "矩阵乘法失败,错误码:" _rc }

这样即使出错,程序也不会中断,你可以根据错误码判断问题所在。

6.3 后续可以扩展的方向

矩阵计算的基础打牢之后,可以往几个方向扩展。一个是mata编程,学写自定义函数和优化算法。另一个是矩阵分解,比如Cholesky分解、特征值分解、奇异值分解,这些在mata里都有对应的函数。还有一个是稀疏矩阵,如果你的数据有很多零元素,用稀疏矩阵存储和运算会快很多,mata里有sparse相关的函数。

不过这些都是后话。对于大多数Stata用户来说,把matrix命令这一套用熟,已经能解决绝大部分问题了。关键是多练、多试、多踩坑。我自己的经验是:看十遍文档不如自己动手写一遍,写十遍不如帮别人排查一个错误。矩阵计算这东西,入门之后就是熟练工种,用得越多,越觉得顺手。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询