温馨提示: 定期 清理浏览器缓存,可以获得最佳浏览体验。
作者: 胡世亮 (河海大学)
E-mail: hushiliang2018@hhu.edu.cn
目录
此文是我在回答【连享会 2020 暑期 Stata 初级班】的一位学员问题后,总结和整理而来。
学员问题的描述如下:
学员导入一份国泰安 高管团队人物特征的数据 (Excel 2007版) 进入 Stata ,但是遇到如下图所示的问题。
可以看到:
(1) 由于学员在导入数据时,没有直接设定第 1 行观测值为变量名,现在数据集的变量名是 Excel 原有的列名称 (A B C D ...),故需要解决变量命名 (nrow
和 rename
) 的问题;
(2) 当前的第 2 行和第 3 行都是中文 (非数值型的字符),需要删除这两行观测,但这两行观测是有信息价值的,可以作为变量的标签名 (labone
和 drop
);
(3) 部分变量显然应该是数值型变量,但因为变量观测值中含有非数值型的字符,故需要进行变量类型的转换 (destring
)。
接下来,我将按照上述 3 个步骤详细阐述我给出的解决方案。
首先,需要安装 2 个外部命令 nrow
和 labone
,安装代码如下:
. ssc install nrow , replace
. ssc install labone , replace
接下来,我简要介绍 nrow
和 labone
命令的语法和选项。
nrow
命令简介在命令窗口键入help nrow
,可知nrow
命令的语法如下:
nrow [row#] [, keep varlist(varlist)]
row#
设定将第 # 行的变量观测值命名为变量名,如果缺省,则默认设定第 1 行的变量观测值命名为变量名;
选项keep
设定保留第 # 行的变量观测值,如果该选项缺省,则默认删除第 # 行的变量观测值;
选项varlist(varlist)
设定需要重命名的变量,如果该选项缺省,则默认对全部变量_all
进行重命名。
值得关注的是,nrow
命令存在一个比较严重的 bug,即当某些变量第 # 行的观测值中存在空格" ",逗号",",井号"#"等特殊符号时,则nrow
命令无法顺利完成重命名。
上述 bug 可以采用正则表达式函数进行解决。
在命令窗口键入 help labone
,可知 labone
命令的语法如下:
labone [varlist] [,options]
varlist
设定需要设定变量标签名的变量列表,如果缺省,则默认对全部变量 _all
设定新的标签名;nrow(numlist)
设定将第 numlist 行的变量观测值命名为变量标签名,其中,numlist 是一组行号的列表,如果该选项缺省,则设定第 1 行的变量观测值命名为变量标签名;concat(concat_strings)
设定指定的字符串连接来自不同行的内容;如果该选项缺省,默认情况下是用空格连接;nospace
设定不采用空格连接不同行的内容。
在这里,由于我手边没有拿到学员的范例数据,我将直接手工输入一份数据集用来演示。
为了说明 nrow
命令的 bug ,我故意在第 1 行观测值中添加了一些特殊符号。
. clear
. input str20 A str20 B str20 C
"_Stkcd#" "5Rept@dt" "Person ID"
证券代码 统计截止日期 人员ID
没有单位 没有单位 没有单位
000529 2009-12-31 30182124
. end
在这里,我们先看一下,如果不去除示例数据集中第 1 行观测值中的特殊符号,直接使用 nrow
命令会出现什么问题。
nrow // 将变量名重命名为第1行的内容,并删除第1行
list , clean noobs // 得到的结果如下
/*
A _5Rept_dt C
证券代码 统计截止日期 人员ID
没有单位 没有单位 没有单位
000529 2009-12-31 30182124
*/
可以看到,A 变量和 C 变量没有成功重命名,而 B 变量虽然成功重命名,但是为了符合 Stata 变量命名的要求,直接在变量开头添加了下划线,且 5Rept@dt 中间的特殊符号被强制替换为下划线"_"。
我们采用支持正则表达式的字符型函数可以解决上述问题,详细代码如下:
clear
input str20 A str20 B str20 C
"_Stkcd#" "5Rept@dt" "Person ID"
证券代码 统计截止日期 人员ID
没有单位 没有单位 没有单位
000529 2009-12-31 30182124
end
*-以下代码用于更改第 1 行 (或第 # 行) 观测值内容,以满足 Stata 变量命名的规则和要求
foreach v of varlist _all {
replace `v' = ustrregexra(`v',"[^\u4e00-\u9fa5a-zA-Z0-9_]","") in 1 // 只保留指定变量第 1 行 (或第 # 行) 观测值内容 (字符串) 中,中文字符、英文字母、数字和下划线
replace `v' = ustrregexrf(`v',"_+","") if ustrregexm(`v',"^_") in 1 // 去除指定变量第 1 行 (或第 # 行) 观测值内容 (字符串) 中,开头的全部下划线 (变量命名时,一般不建议采用下划线开头)
replace `v' = ustrregexrf(`v',"[0-9]+","") if ustrregexm(`v',"^[0-9]") in 1 // 去除指定变量第 1 行 (或第 # 行) 观测值内容 (字符串) 中,开头的全部数字 (变量名是一定不允许数字为开头) ,如果我们不去除开头的全部数字,则在执行 nrow 命令时, Stata 会强制以下划线"_"开头重命名变量名
}
. nrow // 将变量名重命名为第1行的内容,并删除第1行
. list , clean noobs // 得到的结果如下
Stkcd Reptdt PersonID
证券代码 统计截止日期 人员ID
没有单位 没有单位 没有单位
000529 2009-12-31 30182124
可以看到,原变量 A,B,C 都成功被重命名为第 1 行观测值的内容。
采用 labone
命令可以方便快捷地设定变量标签名为指定行的观测值内容。
. rename _all , lower // 采用变量小写形式,这是我的个人习惯,也可以不设定
. labone , nrow(1 2) concat("_") // 将第 1 行(即原第 2 行)和第 2 行设置为标签名,之间用下划线"_"连接
. describe
Contains data
obs: 3
vars: 3
---------------------------------------------------------
storage display
variable name type format variable label
---------------------------------------------------------
stkcd str20 %20s 证券代码_没有单位
reptdt str20 %20s 统计截止日期_没有单位
personid str20 %20s 人员ID_没有单位
---------------------------------------------------------
Sorted by:
Note: Dataset has changed since last saved.
最后,直接使用 drop
命令和 destring
命令完成数据的最终处理。
. drop in 1/2 // 删除前2行观测值
. destring _all , replace // 将变量转换成数值型变量
. format stkcd %06.0f
. list , clean noobs // 得到的结果如下
stkcd reptdt personid
000529 2009-12-31 30182124
至此,我们可以总结出巧妙使用 nrow + labone
命令组合解决变量名和变量标签名重命名问题的关键要点。
本推文使用的全部代码汇总如下:
*- 0. 下载和安装必需的外部命令
cap which nrow
if _rc != 0 {
qui ssc install nrow , replace
}
cap which labone
if _rc != 0 {
qui ssc install labone , replace
}
*- 1. 导入数据到 Stata
clear
input str20 A str20 B str20 C
"_Stkcd#" "5Rept@dt" "Person ID"
证券代码 统计截止日期 人员ID
没有单位 没有单位 没有单位
000529 2009-12-31 30182124
end
*- 2. 采用 nrow 命令解决变量命名问题
*-以下代码用于更改第 1 行 (或第 # 行) 观测值内容,以满足 Stata 变量命名的规则和要求
foreach v of varlist _all {
replace `v' = ustrregexra(`v',"[^\u4e00-\u9fa5a-zA-Z0-9_]","") in 1 // 只保留指定变量第 1 行 (或第 # 行) 观测值内容 (字符串) 中,中文字符、英文字母、数字和下划线
replace `v' = ustrregexrf(`v',"_+","") if ustrregexm(`v',"^_") in 1 // 去除指定变量第 1 行 (或第 # 行) 观测值内容 (字符串) 中,开头的全部下划线 (变量命名时,一般不建议采用下划线开头)
replace `v' = ustrregexrf(`v',"[0-9]+","") if ustrregexm(`v',"^[0-9]") in 1 // 去除指定变量第 1 行 (或第 # 行) 观测值内容 (字符串) 中,开头的全部数字 (变量名是一定不允许数字为开头) ,如果我们不去除开头的全部数字,则在执行 nrow 命令时, Stata 会强制以下划线"_"开头重命名变量名
}
nrow // 将变量名重命名为第1行的内容,并删除第1行
rename _all , lower // 采用变量小写形式,这是我的个人习惯,也可以不设定
*- 3. 采用 labone 命令解决变量标签设定问题
abone , nrow(1 2) concat("_") // 将第1行(即原第2行)和第2行设置为标签名,之间用下划线连接
*- 4. 采用 destring 命令完成变量类型转换
drop in 1/2 // 删除前2行观测值
destring _all , replace // 将变量转换成数值型变量
format stkcd %06.0f
连享会-直播课 上线了!
http://lianxh.duanshu.com
免费公开课:
直击面板数据模型 - 连玉君,时长:1小时40分钟 Stata 33 讲 - 连玉君, 每讲 15 分钟. 部分直播课 课程资料下载 (PPT,dofiles等)
支持回看,所有课程可以随时购买观看。
专题 | 嘉宾 | 直播/回看视频 |
---|---|---|
⭐ 最新专题 ⭐ | DSGE, 因果推断, 空间计量等 | |
⭕ Stata数据清洗 | 游万海 | 直播, 2 小时,已上线 |
研究设计 | 连玉君 | 我的特斯拉-实证研究设计,-幻灯片- |
面板模型 | 连玉君 | 动态面板模型,-幻灯片- |
面板模型 | 连玉君 | 直击面板数据模型 [免费公开课,2小时] |
Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。
关于我们
课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法
等
连享会小程序:扫一扫,看推文,看视频……
扫码加入连享会微信群,提问交流更方便
✏ 连享会学习群-常见问题解答汇总:
✨ https://gitee.com/arlionn/WD