名师讲堂|使用 Stata 计算地方政府竞争衡量指标:矩阵运算的应用

教育   教育   2024-11-07 13:56   安徽  

该课程已经讲完,感兴趣的小伙伴可以点击文末的阅读原文跳转到 RStata 平台观看视频讲解~


「财政研究」2019 年第 4 期中有篇论文<经济分权、地方政府竞争与城市全要素生产率> 提到了衡量政府竞争程度的指标。以往的文献通常采用经济增长率、外商直接投资和宏观税负,背后的逻辑是指标数值越大,代表地方政府竞争越激烈。但是三种方式都无法揭示本地政府受相邻地区地方政府决策的影响,因此该论文提出可以用地区经济增长率与空间权重矩阵的乘积 Wgdpg 衡量地方政府竞争。今天我们就一起来看下如何在 Stata 中通过矩阵运算的方法来计算这一指标。

地区经济增长率通常使用地区生产总值的增长率衡量,这一指标在之前分享的城市统计年鉴面板数据里面有,这里提取了出来:

1999~2022 年中国城市统计年鉴面板数据:https://rstata.duanshu.com/#/brief/course/1dcad8873f394c31a4f082bd74e916b2

  • 1998~2021年各地级市地区生产总值面板数据.dta

另外因为 2018 年的城市统计年鉴(上面的数据是 2017 年的)没有提供全市的地区生产总值,所以我又从 EPS 获取了 2017 年的数据进行补充。

首先读取“2019年各市是否接壤矩阵(对角线为0).xlsx”文件并处理,该文件来源于平台上之前分享的「历年各省市区县邻接矩阵、质心距离矩阵、质心距离倒数矩阵数据」。

历年各省市区县邻接矩阵、质心距离矩阵、质心距离倒数矩阵数据:https://rstata.duanshu.com/#/brief/course/eb331d940dbf4907b75d75b4914da67d

import excel using "2019年各市是否接壤矩阵(对角线为0).xlsx"clear 
foreach i of varlist _all {
 cap replace `i' = subinstr(`i'"-""_", .) if _n == 1
}
nrow 1 

destringreplace 
replace 城市 = subinstr(城市, "-""_", .)
save "2019年各市是否接壤矩阵(对角线为0)"replace 

因为 Stata 中的变量名不支持带“-”号的,所以这里都替换成了“_”。

因为城市统计年鉴里面没有提供 2017 年的全市地区生产总值,所以再从 EPS 获取一份 2017 年的处理下:

*- 2017 年的数据 
use 2017, clear 
ren 城市名称 市 
ren 城市代码 市代码 
ren 国内生产总值万元 地区生产总值_当年价格_亿元_全市
replace 地区生产总值_当年价格_亿元_全市 = 地区生产总值_当年价格_亿元_全市 / 10000 
drop if missing(地区生产总值_当年价格_亿元_全市)
drop 市代码
replace 市 = "北京市" if 市 == "北京" 
save 2017b, replace 

这份数据里面有市代码变量,但是担心可能不是和我们这份城市统计年鉴数据一个版本的,所以匹配下试试:

shp2dta using "2019行政区划/市.shp", database(citycode2019) coord(coord) replace 
cap erase coord.dta 
use citycode2019, clear 
drop *类型 _ID 
merge 1:1 市 using 2017b 
*- 有三个市没有匹配成功就不要了
keep if _m == 3
drop _m 
save "2017c"replace 

然后就可以把 2017 年的数据合并到总数据里面,再补充下缺失值:

*- 补充缺失的增长率
use "1998~2021年各地级市地区生产总值面板数据"clear 
drop if 年份 == 2017
append using 2017c 
gen 城市 = 省 + "_" + 市
encode 城市, gen(city)
xtset city 年份 
replace 地区生产总值增长率_百分比_全市 = ((地区生产总值_当年价格_亿元_全市 - L.地区生产总值_当年价格_亿元_全市) / 地区生产总值_当年价格_亿元_全市) * 100 if missing(地区生产总值增长率_百分比_全市)
drop city 
save "1998~2021年各地级市地区生产总值面板数据(填补后)"replace 

我们再以 2021 年的数据为例看一下如何计算这一指标。

保留 2021 年的数据和矩阵匹配:

use "1998~2021年各地级市地区生产总值面板数据(填补后)"clear 
keep if 年份 == 2021
drop if missing(地区生产总值增长率_百分比_全市)
merge 1:1 城市 using "2019年各市是否接壤矩阵(对角线为0).dta" 
keep if _m == 3
drop _m 

为了避免矩阵的顺序错乱,我们首先锁定数据的行顺序:

*- 首先锁定行的顺序
gen id = _n 

这样如果后面有操作导致行序变了,只需要 gsort id 就可以修正了(不过这个在下面没用到)。

然后根据城市顺序重新排列下列序:

*- 循环获取城市列表
local vlist = ""
forval i = 1/`=_N' {
 local vlist `vlist' `=城市[`i']'
}
keep 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'
order 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'

下面就可以使用 mkmat 命令把变量值转换成矩阵了:

mkmat 地区生产总值增长率_百分比_全市, mat(m1)
mkmat `vlist'mat(m2)

注意这里也用到了 vlist,试过 local 变量。local 变量的定义和使用要一并运行,所以这里的代码要和上面的一段代码同时运行才可以。

这样的话,m1 就是个 nxn 的矩阵,m2 是 nx1 的矩阵,两者相乘就得到了 nx1 的矩阵:

mat Wgdpg = m2 * m1 

keep 省代码 省 市代码 市 
svmat Wgdpg

list in 1/10 

*>     +------------------------------------------------------+
*>     | 省代码   省             市代码   市           Wgdpg1 |
*>     |------------------------------------------------------|
*>  1. | 310000   上海市         310000   上海市         26.2 |
*>  2. | 530000   云南省         530900   临沧市         12.8 |
*>  3. | 530000   云南省         530700   丽江市          8.3 |
*>  4. | 530000   云南省         530500   保山市          7.4 |
*>  5. | 530000   云南省         530100   昆明市        31.16 |
*>     |------------------------------------------------------|
*>  6. | 530000   云南省         530600   昭通市        39.87 |
*>  7. | 530000   云南省         530800   普洱市        16.46 |
*>  8. | 530000   云南省         530300   曲靖市         38.6 |
*>  9. | 530000   云南省         530400   玉溪市         10.4 |
*> 10. | 150000   内蒙古自治区   150900   乌兰察布市    38.55 |
*>     +------------------------------------------------------+

svmat 可以把矩阵再转换成变量。

然后就可以循环所有年份的了:

*- 循环所有年份
cap mkdir "结果数据"
use "1998~2021年各地级市地区生产总值面板数据(填补后)"clear 
forval i = 1998/2021 {
 preserve 
 qui {
  keep if 年份 == `i' 
  drop if missing(地区生产总值增长率_百分比_全市)
  merge 1:1 城市 using "2019年各市是否接壤矩阵(对角线为0).dta" 
  keep if _m == 3
  drop _m 

  local vlist = ""
  forval j = 1/`=_N' {
   local vlist `vlist' `=城市[`j']'
  }
  keep 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'
  order 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'

  *- 构建矩阵
  mkmat 地区生产总值增长率_百分比_全市, mat(m1)
  mkmat `vlist'mat(m2)
  mat Wgdpg = m2 * m1 

  keep 省代码 省 市代码 市 
  svmat Wgdpg
 }
 save "结果数据/`i'"replace 
 restore 

最后合并所有年份的就得到了总的计算结果:

use 结果数据/1998.dta, clear 
gen 年份 = 1998 
forval i = 1999/2021 {
 append using 结果数据/`i'.dta
 replace 年份 = `i' if missing(年份)
}
order 年份 
ren Wgdpg1 Wgdpg

list in 1/10

*>     +------------------------------------------------------------+
*>     | 年份   省代码   省             市代码   市           Wgdpg |
*>     |------------------------------------------------------------|
*>  1. | 1998   310000   上海市         310000   上海市          34 |
*>  2. | 1998   530000   云南省         530100   昆明市         7.2 |
*>  3. | 1998   530000   云南省         530300   曲靖市        19.1 |
*>  4. | 1998   150000   内蒙古自治区   150300   乌海市         8.9 |
*>  5. | 1998   150000   内蒙古自治区   150200   包头市        13.1 |
*>     |------------------------------------------------------------|
*>  6. | 1998   150000   内蒙古自治区   150100   呼和浩特市      21 |
*>  7. | 1998   150000   内蒙古自治区   150400   赤峰市        13.1 |
*>  8. | 1998   110000   北京市         110000   北京市        56.5 |
*>  9. | 1998   220000   吉林省         220200   吉林市        68.2 |
*> 10. | 1998   220000   吉林省         220300   四平市        67.4 |
*>     +------------------------------------------------------------+

save "Wgdpg计算结果"replace 

另外如果是区县的可能使用 Mata 的矩阵运算会更快速点,首先以 2021 年的为例:

clear all
use "1998~2021年各地级市地区生产总值面板数据(填补后)"clear 
keep if 年份 == 2021
drop if missing(地区生产总值增长率_百分比_全市)
merge 1:1 城市 using "2019年各市是否接壤矩阵(对角线为0).dta" 
keep if _m == 3
drop _m 

*- 循环获取城市列表
local vlist = ""
forval i = 1/`=_N' {
 local vlist `vlist' `=城市[`i']'
}
keep 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'
order 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'

mata
m1 = st_data(., "`vlist'")
m2 = st_data(., "地区生产总值增长率_百分比_全市")
Wgdpg = m1 * m2 
st_matrix("Wgdpg", Wgdpg)
end 

keep 省代码 省 市代码 市 
svmat Wgdpg

循环所有年份可以采用下面的代码:

*- 由于 mata 程序里面有 end,所以不能直接用在 循环里面,首先定义一个 mata 函数:

clear all 
mata:
void matfun() {
 vlist = st_local("vlist")
 m1 = st_data(., vlist)
 m2 = st_data(., "地区生产总值增长率_百分比_全市")
 Wgdpg = m1 * m2 
 st_matrix("Wgdpg", Wgdpg)
}
end 

cap mkdir "结果数据2"
use "1998~2021年各地级市地区生产总值面板数据(填补后)"clear 
forval i = 1998/2021 {
 preserve 
 qui {
  keep if 年份 == `i' 
  drop if missing(地区生产总值增长率_百分比_全市)
  merge 1:1 城市 using "2019年各市是否接壤矩阵(对角线为0).dta" 
  keep if _m == 3
  drop _m 

  local vlist = ""
  forval j = 1/`=_N' {
   local vlist `vlist' `=城市[`j']'
  }
  keep 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'
  order 年份 省代码 省 市代码 市 地区生产总值_当年价格_亿元_全市 地区生产总值增长率_百分比_全市 城市 `vlist'

  mata: matfun()

  keep 省代码 省 市代码 市 
  svmat Wgdpg
 }
 save "结果数据2/`i'"replace 
 restore 

合并代码就和上面的一样了。

课程信息

该课程已经讲完,感兴趣的小伙伴可以点击文末的阅读原文跳转到 RStata 平台观看视频讲解~

  1. 直播地址:腾讯会议(需要购买 RStata 名师讲堂会员参加)
  2. 讲义材料:需要购买 RStata 名师讲堂会员,详情可阅读:一起来学习 R 语言和 Stata 啦!学习过程中遇到的问题也可以随时提问!

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

附件下载(点击文末的阅读原文即可跳转):

https://rstata.duanshu.com/#/brief/course/2cfc2c6307bc401b861d0b435e286fff


RStata
一起学习 R 语言和 Stata 吧!
 最新文章