温馨提示:若页面不能正常显示数学公式和代码,请阅读原文获得更好的阅读体验。
作者:丁闪闪 (连享会)
邮箱:lianxhcn@163.com
- Title: Stata 数据合并:gvkey 补齐 6 位编码再 merge
- Keywords: Compustat, CRSP, IBES, GVKEY, merge, 数据清洗, 横向合并, 添加零字符, 字符串补零
1. 简介
在处理 Compustat、CRSP、IBES 等数据库的美股数据时,GVKEY几乎是绕不过去的主键之一。最常见的使用场景是:你在做公司层面 (firm-level)的合并,比如把财务报表数据和股票市场数据拼接起来,GVKEY往往就是关键的 merge 变量。
但实际操作时,GVKEY很容易"看起来一样,merge 却对不上"。原因通常不是数据本身错了,而是存储类型和编码格式不一致:
- 有些数据库里是
gvkey(数值型),例如1004 - 有些数据库里是
GVKEY(字符型),例如"001004" - 有些数据已经是足额 6 位字符编码
- 有些数据是"不足六位但不补零"的写法 (比如
"1004")
因此,merge 前至少要检查两件事:
- (1)变量类型一致:两边都必须是 numeric 或 string,不能一边数值一边字符串
- (2)补零非常关键:
1004和"001004"在 merge 里是两回事
本文用一个小例子,介绍几种常用的方法,说明如何把数值型gvkey统一处理成 6 位字符串编码。
2. 数据和目标
我们先生成一份包含 5 行观测值的数据,gvkey为数值型:
clear input gvkey 201 1004 11008 123456 999999 end我们期待最终得到的 6 位编码:
201→"000201"1004→"001004"11008→"011008"123456→"123456"999999→"999999"
目标是生成一个新变量:
- 变量名:
GVKEY - 类型:字符串
str6 - 规则:不足 6 位,左侧补零
3. 首选方案:tostring + format(%06.0f)
由于gvkey是数值型变量,我们可以使用tostring命令将其转换为字符串变量,并使用format(%06.0f)来补齐 6 位编码。
tostring gvkey, gen(GVKEY) format(%06.0f) list gvkey GVKEY, clean结果如下:
. list gvkey GVKEY, clean gvkey GVKEY 1. 201 000201 2. 1004 001004 3. 11008 011008 4. 123456 123456 5. 999999 999999解读:
tostring gvkey:把数值型gvkey转成字符串变量gen(GVKEY):生成新变量名为GVKEYformat(%06.0f):把数值按"6 位整数"输出%06.0f的含义是:总宽度 6 位、整数输出、小数位为 0、不足位数左侧补 0。即201被格式化为"000201";1004被格式化为"001004";而123456则维持原样"123456"。
4. 其他可选方案
下面的方案都能实现同样的目标。为了方便你在同一个 dofile 里多种写法一起跑,我把新变量命名为GVKEY_A,GVKEY_B, ...,避免报错覆盖。
4.1 方案 A:string()+ 格式%06.0f
gen str6 GVKEY_A = string(gvkey, "%06.0f") list gvkey GVKEY_A, clean结果同上,不在列示。具体解释如下:
string(x, "%06.0f"):把数值变量x转为字符串,并按 6 位补零格式输出- 优点是:写法像 "定义规则",可读性很强
- 缺点是:需要你在
gen时显式指定str6。因此,当变量长度超过 6 位时,需要手动调整str类型的长度。
4.2 方案 B:字符串拼接补零 + 取最后 6 位
这个方法常见于各种 "编码补齐" 的场景,本质是:
- 先把数字转字符串
- 左边拼 6 个 0
- 再截取最后 6 位
tostring gvkey, gen(gvkey_str) format(%12.0f) force gen str6 GVKEY_B = substr("000000" + gvkey_str, -6, 6) list gvkey gvkey_str GVKEY_B, clean解释:
"000000" + gvkey_str:把 6 个 0 拼到左侧substr(..., -6, 6):从末尾开始,取字符串最后 6 位- 优点:速度快、技巧通用;可以将
"000000"替换为任意长度的补零字符串;也可以用于在字符串左侧补齐其它字符,如"xxxxxx"+gvkey_str。 - 缺点:可读性略差,且多一个中间变量
扩展:有些情况下我们需要在字符串右侧补齐字符,这种方法就很有用。例如:
gen str6 GVKEY_C = substr(gvkey_str + "xxxxxx", 1, 6) list gvkey gvkey_str GVKEY_C, clean结果如下;
. list gvkey gvkey_str GVKEY_C, clean gvkey gvkey_~r GVKEY_C 1. 201 201 201xxx 2. 1004 1004 1004xx 3. 11008 11008 11008x 4. 123456 123456 123456 5. 999999 999999 9999995. 类似场景
GVKEY的补零问题,本质上属于一类非常普遍的数据清洗任务:把"看起来像编号"的变量统一为固定长度的字符串编码。
只要你做过跨数据库合并、跨系统匹配、或者需要把编码输出到表格/图形里,类似的问题几乎一定会遇到。
下面补充一些典型场景,便于你快速形成迁移思路。
中国上市公司代码补齐 6 位 (证券代码 / 股票代码)
在 Wind、CSMAR、交易所公告、券商研报等来源之间切换时,经常出现一边是数值型4、638,另一边是字符串"000004"、"000638"。如果不补零,merge 会直接掉匹配。行政区划代码 (6 位) 或统计地理编码 (省市县)
地理编码在不同来源里经常出现"截断/省略"的情况,例如把"440305"存为数值440305还好,但如果某些系统导出时把前导零抹掉,或者采用"省-市-县分列"的方式,就很容易造成口径不一致。涉及到空间匹配、区域合并、政策试点识别时尤其常见。邮政编码 ZIP / Postcode (长度固定,但前导 0 极其关键)
典型例子是美国 ZIP Code:02138(Cambridge, MA) 这类邮编前面有 0。
一旦被当作数值型导入,就会变成2138,导致你按邮编 merge、分组统计、或做地理映射时出现系统性错误。
温馨提示:若页面不能正常显示数学公式和代码,请阅读原文获得更好的阅读体验。