FEATURED · 精选文章

Stata中gvkey前导零丢失?学会补齐6位编码再merge,避免样本量骤减

发布时间 / 2026/9/10 2:16:02
来源 / 创域科博编辑部
栏目 / 资讯中心
Stata中gvkey前导零丢失?学会补齐6位编码再merge,避免样本量骤减 最近整理一份从 WRDS 下载的 Compustat 数据时碰到一个相当隐蔽的坑明明是用 gvkey 做 merge代码也没报错但合并出来的样本量只有预想的六成。翻数据才发现左边数据集的 gvkey 是带前导零的字符串比如001234右边数据集却是整数1234。在 Excel 里中转一次后公司标识码的前导零被自动吞掉了两边键值长得不一样Stata merge 自然不肯配对。这类问题在会计、金融实证里太常见了尤其是用过 Compustat、CRSP、CSMAR 这类数据库的同学几乎迟早会遇到。gvkey 看起来只是个小变量丢了前导零后果却是 merge 匹配失败、样本量骤减、回归结果对不上。这篇文章就把我排查到解决的全过程写清楚核心就一句话merge 前先确认 gvkey 的数据类型和位数按规则补齐 6 位编码再合并。代码直接给原理也讲明白无论你是刚学 Stata 的硕士生还是长年处理面板数据的青椒应该都能直接抄作业。1. 问题根源gvkey 的前导零是怎么丢的1.1 gvkey 到底是什么为什么必须是 6 位gvkey 是 Compustat 数据库里的全局公司标识码全称 Global Company Key听起来高大上本质就是每家公司的固定编号。这套编码体系有个特点定长 6 位缺位用前导零补齐。比如某公司编号是1234在数据库里正式写法就是001234而不是1234。为什么非得定长因为数据库在处理标识码时定长字符串既好存储又好索引。更重要的是定长能消除歧义。如果允许1234和001234同时存在你怎么知道它们是同一家公司必须用 6 位定长才能保证全局唯一性。问题就出在这里人类习惯省零机器习惯严格匹配。你在 Excel 里看到001234觉得这就是 1234但 Stata 不知道。Stata merge 按精确值匹配001234不等于1234差一位零就匹配不上。所谓 gvkey 补齐 6 位编码再 merge本质就是让键值回到数据库的原始规范。1.2 前导零丢失的三种常见场景我在实际处理中见过 gvkey 前导零丢失的渠道主要有三个基本覆盖了九成情况第一种CSV 或 txt 文件被 Excel 打开后另存。这是最常见的。Excel 的单元格默认“常规”格式打开包含001234的 CSV 时它会“智能”地把这串数字当成数值处理前导零直接消失。更麻烦的是Excel 还会把超过 15 位的长数字转成科学计数法不过 gvkey 只有 6 位主要就是丢零。第二种import excel导入时 Stata 自动推断类型。如果你直接import excel导入原始 Excel 文件而该列在 Excel 里已经被识别为数值格式Stata 读进来后 gvkey 自然是数值型变量。此时你看到的可能是1234、5678这样的整数前导零在源文件里就已经没了。第三种不同数据集的来源渠道不同。有些平台下载的 gvkey 是字符串001234有些则是数值1234。两边单独看都正常放一起 merge 就出问题。这种最坑因为它不是数据本身错了而是格式不统一。1.3 快速定位一段命令确认是否踩坑遇到 merge 结果不对别急着改代码先用命令检查一下你的 gvkey 到底是什么状态。我通常会做三件事use 你的数据.dta, clear describe gvkey count if length(string(gvkey)) 6 list gvkey in 1/20describe能直接告诉你 gvkey 是数值型还是字符串型。如果是数值型length(string(gvkey)) 6会统计出有多少条不是 6 位数量大于 0 基本就中招了。然后再list看具体值你可能会看到1234、5678这种被压缩过的编号。如果是字符串型变量命令改成count if length(gvkey) 6就行。此外我还习惯顺手检查一下有没有空格混进去count if gvkey ! trim(gvkey)空格这东西看不见摸不着但同样会导致 merge 失配。如果这一步已经发现端倪那就直接进入下一节补齐 6 位编码。2. 补齐 6 位编码三种可靠方法对比2.1 避坑认知format 命令不能真正补零很多初学者甚至一些老手上来就用format gvkey %06.0f以为这样就把 gvkey 补成 6 位了。这是一个大坑。format命令只改变变量的显示格式不改变存储值和底层类型。什么意思用%06.0f格式化后Stata 在数据编辑器里会显示001234看起来确实补齐了。但变量实际存储的值仍然是数值1234。merge 匹配时用的是实际值不是显示值所以格式化之后重新 merge结果和之前一模一样匹配失败的样本还是匹配失败。这个坑我踩过一次花了半小时反复 merge始终找不到原因最后用list gvkey, clean才发现值根本就没变。所以记住format 只是化妆不是整容。真正要补零必须生成一个新的字符串变量或者在字符串形式上做处理。2.2 方法一字符串拼接补零如果 gvkey 已经是字符串型但位数不足可以直接用字符串拼接。思路很简单先在前面拼上足够多的零再按 6 位截断。tostring gvkey, replace replace gvkey substr(000000, 1, 6 - length(gvkey)) gvkey if length(gvkey) 6逻辑就是取000000的前6 - length(gvkey)位拼到原变量前面。比如 gvkey 是1234长度 4substr(000000, 1, 2)得到00再拼接为001234。这个方法有个前提gvkey 必须是纯数字字符串不能含有非数字字符。如果数据里有缺失值length为 0substr(000000, 1, 6)会得到000000可能把缺失值错误地变成000000这个要注意。所以补零之前先处理缺失或者加上条件replace gvkey substr(000000, 1, 6 - length(gvkey)) gvkey if length(gvkey) 6 gvkey ! 2.3 方法二string() 数值格式化我实际更常用的是string()函数它可以直接把数值转成指定格式的字符串一步到位。replace gvkey string(real(gvkey), %06.0f)这里的real(gvkey)把字符串或数值统一转成数值string(..., %06.0f)再格式化成 6 位字符串。一行代码就完成了“类型转换 补零”。比如原始值是数值1234real(1234)还是1234string(1234, %06.0f)得到001234。如果原始值是字符串5678同样能得到005678。这个方法的健壮性比方法一好因为它天然处理了不同类型的输入。唯一的坑是如果 gvkey 里有非数字字符real()会返回缺失值string(缺失值, %06.0f)也会是缺失不会报错但数据会变成.。所以跑之前先确认数据没有混入字母或符号。2.4 方法三保留原变量另建补零变量有些场景下你不想动原始变量尤其是还要用数值型 gvkey 做其他计算时。这时可以新建一个字符串变量专门用来 merge。gen gvkey_str string(gvkey, %06.0f)这个方法的优势是原数据不动新变量只负责“连接”任务。操作完直接merge 1:1 gvkey_str using ...完全不影响后续分析。我处理多个数据源时经常这么干因为每个数据集里的 gvkey 类型可能都不一样统一生成一个gvkey_str作为唯一键方便对照。2.5 方法对比和选择建议三种方法各有适用场景我先整理成一个表方便你按实际情况选方法适用场景优点注意点字符串拼接补零gvkey 已是字符型且为纯数字逻辑直观不涉及类型转换需处理空值和异常长度string(real())格式化数值型或字符型均可一行代码同时转换补零兼容性强有非数字字符时会生成缺失值另建gvkey_str变量不想改动原始变量的场景原数据保留灵活安全会多占一列空间我个人习惯是只要 gvkey 是纯数字首选string(real(gvkey), %06.0f)简单省事如果数据本身不干净先清理再补零。用replace gvkey string(real(gvkey), %06.0f)统一覆盖原变量也行但前提是你确认原始 gvkey 以后用不到了。3. merge 实操主键确认、完整代码、结果检查3.1 合并前确认主键唯一性gvkey 补齐 6 位之后就能直接 merge 吗还差一步确认键变量的唯一性。很多人只盯着格式忘了主键本身的业务含义结果又踩另一个坑。合并之前先想清楚你的数据长什么样。比如公司财务数据如果每个公司每年一行那唯一键就是gvkey year单独用gvkey当键就不合适。如果只是公司层面的静态数据才可以用gvkey单独当键。用isid或者duplicates检查一下isid gvkey year duplicates report gvkey如果isid报错说明这个组合不能唯一标识每一个观测你要么加变量要么考虑是不是数据本身有重复。别跳过这步我用1:1 merge时经常因为忘记检查 using 数据被 Stata 报do not uniquely identify observations的错回来查才发现是辅助数据集有重复行。3.2 完整代码示例两个数据集都补一遍再合并下面给一套可以直接运行的完整流程。假设你有两个数据集master.dta公司财务数据包含 gvkey数值型丢了前导零、year、roa、levstock.dta股票收益数据包含 gvkey字符串型带前导零、year、ret这两个数据集的 gvkey 格式不一样如果直接 merge大概率要么 type mismatch要么大量匹配不上。正确处理是把两个文件都统一成同一种格式。* 第一步处理 master 数据集 use master.dta, clear describe gvkey * 统一转成 6 位字符串 tostring gvkey, replace replace gvkey string(real(gvkey), %06.0f) if gvkey ! compress gvkey * 检查主键 isid gvkey year save master_pad.dta, replace * 第二步处理 stock 数据集 use stock.dta, clear describe gvkey * 先去掉可能存在的空格 replace gvkey trim(gvkey) * 统一转成 6 位字符串 replace gvkey string(real(gvkey), %06.0f) if gvkey ! compress gvkey * 检查主键 isid gvkey year save stock_pad.dta, replace * 第三步正式合并 use master_pad.dta, clear merge 1:1 gvkey year using stock_pad.dta * 查看合并结果 tab _merge这一步里tostring把数值型 gvkey 转成字符串replace gvkey string(real(gvkey), %06.0f)负责补零。两个文件经过同样处理后gvkey 都是 6 位字符串类型一致、值域对齐merge 才能顺利跑通。3.3 merge 类型怎么选1:1、1:m、m:1很多刚开始写 merge 的同学对 1:1、1:m、m:1 的区别不够敏感结果是代码没报错但合并逻辑是错的。我一般用一个简单方法判断看键值在两侧唯一性组合。如果 master 和 using 中键值组合都唯一用1:1。如果 master 中键值唯一using 中有多个记录对应同一个键值用1:m。如果 master 中有多条记录对应同一个键值using 中键值唯一用m:1。举例来说你想在公司层面数据每个公司只有一行上合并股票收益年度数据每个公司每年都有很多行那就应该是merge 1:m gvkey using stock_pad.dta如果反过来你的主数据集是公司-年度面板而辅助数据集是公司层面的静态信息就要写成merge m:1 gvkey using company_info_pad.dta一旦用错类型Stata 不一定报错但结果可能不是你想要的。比如该用 1:m 却用了 1:1如果 using 侧键值有重复Stata 会直接报错如果 using 侧恰好唯一那语法上跑通了但你的分析逻辑就错了。先判断逻辑再写命令这比记语法重要得多。3.4 合并后的快速验证merge 跑完不是终点我每次都会做一轮快速验证确认合并结果符合预期。第一看_merge分布tab _merge如果_merge 1和_merge 2的数量都比较大说明两边都有匹配不上的样本。此时要区分两种情况一种是正常现象比如业务上某些公司本来就只有一边的数据另一种则是问题信号比如 gvkey 格式没补齐两边各写各的。我习惯抽几个未匹配样本手动看list gvkey year if _merge 1 in 1/10 list gvkey year if _merge 2 in 1/10如果gvkey显示出来明显是同一批公司但就是没配上那大概率还是有格式问题比如一侧是字符串001234另一侧是字符串1234补零没补全。如果是预期内全匹配可以进一步断言assert _merge 3这行命令如果没报错说明所有观测都成功匹配之后就可以安心drop _merge继续后续分析了。4. 常见问题排查与避坑实录4.1 _merge 变量到底在告诉你什么merge 完成后Stata 会自动生成一个_merge变量取值 1、2、3分别代表三种情况_merge 1只出现在主数据集 master 中using 里没有对应键值_merge 2只出现在辅助数据集 using 中master 里没有对应键值_merge 3两个数据集都匹配上了这个变量简直是排查线索的富矿。我见过太多人 merge 完直接drop _merge然后看着样本量不对劲又不知道问题出在哪。实际上先tab _merge看分布一眼就能定位问题方向。如果_merge 1和_merge 2都特别多同时_merge 3只有很小比例优先怀疑键值格式不统一。如果_merge 2特别多而你预期 using 数据应该大部分能匹配上那可能是 using 数据集本身有问题。总之merge 完先看 _merge再决定下一步这是低成本高收益的好习惯。4.2 高频问题速查表我把几年里被反复问到的问题整理成一个速查表按现象、原因、办法三列罗列遇到问题可以直接对号入座现象常见原因解决办法merge 报 type mismatch两侧 gvkey 类型不一致一侧数值型一侧字符串型统一转成字符串再补零merge 报 do not uniquely identify observations in using datausing 数据里 gvkey 重复却用了 1:1改成 1:m 或 m:1或先 dups dropmerge 后 _merge 3 极少前导零丢失两侧键值表示不一致用 string(real(gvkey), %06.0f) 补零补零后发现缺失值原始 gvkey 有非数字字符或空值先清洗剔除或标记异常值merge 结果变量被改名成 var2两个数据集有同名非键变量用 rename 或 keep 指定保留变量前三个问题占了 gvkey 相关报错的八成以上。尤其是 type mismatch 和重复观测基本上都是因为在合并前没有做统一的键值检查和预处理。4.3 一个容易误判的怪问题还有一种情况比较隐蔽我在群里看到不止一个同学踩过gvkey 在 Stata 里明明显示是 6 位但 merge 还是大量失败。仔细查才发现一侧的 gvkey 是字符串但是 str4 类型比如1234另一侧是 str6 类型比如001234。两边看起来都是字符串但底层存储宽度不一样值域占位完全不同自然匹配不上。Stata 的字符串类型是有长度属性的str4 和 str6 在 merge 时也要严格一致。解决办法就是重复我上面那套流程tostring gvkey, replace然后replace gvkey string(real(gvkey), %06.0f)把两侧都转成 str6。另外如果你在网上搜到 “outcome does not vary” 这类报错那是 xtlogit、clogit 这类模型在特定数据形态下才会出现的问题跟 merge 没关系。别把两个问题混在一起排查否则会白绕一圈。5. 让 ID 归一化成为习惯工程化心得5.1 把补齐逻辑封装成程序gvkey 补齐这种操作只做一次当然无所谓但如果你和我一样经常要处理多个数据集就很建议把它封装成一个 Stata 程序随手调用。cap program drop pad_gvkey program define pad_gvkey cap tostring gvkey, replace replace gvkey trim(gvkey) replace gvkey string(real(gvkey), %06.0f) if gvkey ! replace gvkey if gvkey 000000 compress gvkey end以后每次打开数据集先pad_gvkey一把梭再检查主键、merge流程就变得非常机械化。最后一行把000000还原成缺失是为了防止原本的空值被错误补零。这个细节我是吃了亏才加上的当时一批空 gvkey 全变成000000合并完多出一堆假公司记录排查花了好久。5.2 其他 ID 编码同样适用别以为只有 gvkey 有前导零问题。CRSP 里的 PERMNO、美国证券委员会的 CIK、国际证券识别码 ISIN甚至一些自定义编码都可能是定长的都可能存在前导零被 Excel 吞掉的情况。处理逻辑完全一样先判断类型再统一格式最后补零。所以这篇文章虽然标题写的是 gvkey但你完全可以把它当成一套 ID 归一的通用方法。遇到 PERMNO 就把变量名换一下代码直接用。5.3 我踩过几次坑之后的个人操作习惯讲点实际的。我现在处理任何涉及 ID 变量的数据已经养成了一套固定动作下载数据后第一件事就是检查关键 ID 变量的类型和位数而不是等到 merge 报错才回头查。这个习惯是在连续两次样本量莫名减半后痛定思痛养成的。数据下载完先统一归一后续 merge 环节就是水到渠成的事。还有一个小技巧尽量别让原始数据过 Excel 的手。从 WRDS 下载 CSV 后如果只是简单看看那没问题但如果要保存并继续用直接留给 Stata 处理别在 Excel 里另存为。很多前导零丢失问题源头都在 Excel 的“好心帮忙”。如果实在要在 Excel 里查看建议把 gvkey 列格式预设为文本或者用import excel时指定该列类型。高版本的 Stata 支持通过import excel, stringcols(列号)强制按文本导入这一点对 ID 类变量特别有用。处理 gvkey 补齐 6 位编码再 merge本质上不是多高深的技术难题而是对数据规范性的尊重。数据库花了大力气做出来的定长编码到了分析这一步如果因为格式不统一而断送掉实在太可惜。每次 merge 前多花两分钟检查类型和位数后续能省下大量排查时间。这套流程虽然简单但能实打实让你少掉头发。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻