净利润率为零的公司年观测扎堆出现时,先别急着跑回归:真实盈利能力几乎不可能「精确等于 0」,一堆恰好为 0 的 ROA,最常见的解释是缺失值在数据清洗时被填成了 0。最小值恰好卡在 0、左尾密密麻麻压在 0 上的样本,直接拿去估均值回归或截尾统计,结果都会被这些点拉偏。下面这份 Stata 模板按三步走:定位 0 值、排查来源、再做截尾前后对照。
第一步:定位 ROA=0 的样本
- use firm_year.dta, clear // 变量:stkcd year roa profit assets
- inspect roa // 分布、特殊值、0 的占比一眼可见
- count if roa == 0 // 精确等于 0 的观测数
- tab year if roa == 0 // 0 值按年份的分布
- tab industry if roa == 0 // 0 值按行业的分布
inspect 会列出负值、零、整数与小数各自的个数,是判断「0 是孤立点还是堆积点」最快的命令。如果 count 显示 0 值占样本比例不小,又集中在特定年份或行业,优先怀疑数据录入环节,而不是企业恰好不盈不亏。
第二步:排查 0 的来源
ROA 是分子除以分母,0 只可能来自分子、分母或二者:
- count if profit == 0 & roa == 0 // 分子(净利润)被填 0
- count if assets == 0 & roa == 0 // 分母(总资产)被填 0
- list stkcd year profit assets roa if roa == 0 in 1/20
如果保留了清洗前的原始字段(比如未处理的净利润),再补一句对照:原始值为缺失、而清洗后变成 0 的观测,就是「缺失填 0」的直接证据。判定为缺失填 0 的,应把 ROA 改回缺失而不是当真实值保留;判定不了的要回到原始报表逐条核对,模板只负责输出定位与分布证据,不代替这步判断。
第三步:截尾前后对照
确认保留 0 值(或怀疑极端值不只在 0 处)时,做缩尾对照:
- ssc install winsor2, replace // 外部命令,首次使用先安装
- winsor2 roa, cuts(1 99) suffix(_w1)
- summarize roa roa_w1, detail
- tabstat roa roa_w1, stat(n mean p1 p5 p50 p95 p99 min max) columns(statistics)
缩尾把超出 1% 和 99% 分位数的值改为对应分位数值,样本量不变;如果想让极端值直接退出样本,用剔除而不是缩尾,两者对系数的影响方向可能不同。严格的做法是 roa 与 roa_w1 各跑一次基准回归,把两组系数都报出来,而不是只报截尾后那一组。
两个常见误判
一是把数据环节引入的假 0 当成真实观测:gen roa = profit/assets 在 profit 缺失时生成的是缺失而非 0,假 0 多发生在清洗之后的环节——例如把宽表转长表时用 0 填充空缺年份、或从 Excel 透视表导出时空值被计为 0。排查时看 0 值是否恰好落在面板的补齐年份上。二是把「净利润接近 0」与「ROA 等于 0」混为一谈:前者在 inspect 里显示为大量小数,是真实的微利观测,不该被清洗掉;后者是精确相等,才值得按上面的流程处理。
模板的使用边界
变量名按自己的库改:模板假设 stkcd year roa profit assets 五个字段。winsor2 是 SSC 上的外部命令,换机器要重装。0 值占比很高的样本(比如超过 5%)不建议只靠缩尾处理,应单独做一组剔除 0 值的敏感性分析:reg y x if roa != 0, robust 与缩尾后的结果并列报告。
inspect 的完整语法与示例见 Stata 官方手册的 [D] inspect 条目,PDF 地址在论坛币区。
────────────────
回复后可见:Stata [D] inspect 手册 PDF 地址,以及模板使用的两条补充说明。


雷达卡


京公网安备 11010802022788号







