金融数据分析的第一步往往是从CSV文件开始。以CSMAR数据库为例,下载的上市公司财务数据通常包含多个CSV文件,每个文件对应不同的财务指标。这些原始数据往往存在格式不统一、冗余信息多等问题,需要先进行标准化处理。
我处理过上百个CSMAR数据集,发现最常见的三个痛点是:股票代码格式混乱、报表类型混杂、日期格式不统一。举个例子,某次分析中我发现同一个公司的股票代码在不同文件中分别显示为"000001"、"1"和"平安银行",这会导致后续合并时无法匹配。解决方法是用destring命令统一格式:
stata复制// 统一股票代码格式
destring stkcd, replace ignore(" ")
format stkcd %06.0f
日期处理更是个技术活。CSMAR的日期字段通常形如"2020-12-31",但我们需要提取年份作为面板数据的时序标识。这里推荐使用substr配合destring:
stata复制// 提取年份并转换为数值型
gen year = substr(enddate,1,4)
destring year, replace
报表筛选也很关键。上市公司会同时发布合并报表(A)和母公司报表(B),我们通常只需要合并报表。用这个命令一键筛选:
stata复制keep if typrep == "A"
小技巧:在CSMAR下载数据时就可以添加筛选条件,只下载合并报表和年报数据,能节省大量预处理时间。
数据清洗的核心环节是合并多个数据源。Stata的merge命令看似简单,但实际使用时处处是坑。根据我的项目经验,90%的合并错误都源于对合并类型理解不清。
这是最基础的合并方式,要求两个数据集中的关键变量组合必须唯一。比如按股票代码和年份合并资产负债表和利润表:
stata复制// 先对两个数据集排序
sort stkcd year
save balance_sheet.dta, replace
sort stkcd year
save income_statement.dta, replace
// 执行合并
use balance_sheet.dta, clear
merge 1:1 stkcd year using income_statement.dta
// 清理合并结果
keep if _merge == 3
drop _merge
注意:务必检查
_merge变量的值,3表示匹配成功,1表示只在主数据中存在,2表示只在using数据中存在。
当主数据包含重复的关键变量,而using数据中关键变量唯一时使用。比如将公司基本信息(唯一)合并到财务数据(可能包含多年数据):
stata复制// 确保using数据的关键变量唯一
duplicates report stkcd // 检查重复值
duplicates drop stkcd, force // 如有重复强制删除
// 执行合并
merge m:1 stkcd using company_info.dta
踩坑记录:我曾遇到过using数据存在隐藏重复值导致合并结果异常的情况。现在每次合并前都会先用duplicates report仔细检查。
除了基础的merge,实际项目中还需要应对各种特殊情况。比如当关键变量存在轻微不一致时,可以考虑模糊匹配。
当公司名称存在"腾讯控股"与"腾讯控股有限公司"这类差异时,可以用reclink进行模糊匹配:
stata复制// 安装reclink命令
ssc install reclink
// 执行模糊匹配
reclink company_name using other_file.dta, idmaster(stkcd) idusing(other_id)
合并后数据经常会出现异常值,我总结了一套检查流程:
tab _merge查看匹配成功率misstable sum快速定位缺失变量sum var, detail查看分布情况stata复制// 快速检查数据质量
misstable sum
tabstat assets profit, stats(n mean sd min max) by(_merge)
虚拟变量(dummy variable)是计量分析的重要工具。以创建企业产权性质虚拟变量为例,演示从原始分类变量到分析用虚拟变量的完整流程。
假设原始变量equitynature包含"国企"、"民营"、"外资"等分类,要创建国企虚拟变量:
stata复制// 方法1:直接生成
gen SOE = (equitynature == "国企") if !missing(equitynature)
// 方法2:分步生成(更易读)
gen SOE = 0
replace SOE = 1 if equitynature == "国企"
replace SOE = . if missing(equitynature)
当需要将分类变量转换为多组虚拟变量时,可以用tabulate, gen()命令快速生成:
stata复制// 生成所有制虚拟变量组
tabulate equitynature, gen(own_)
// 重命名生成的虚拟变量
rename own_1 SOE
rename own_2 Private
rename own_3 Foreign
经验分享:在面板数据分析中,我习惯将虚拟变量与年份交互,以捕捉政策变化的时变效应:
stata复制// 创建年份-所有制交互项
forvalues y = 2010/2020 {
gen SOE_`y' = SOE * (year == `y')
}
完成所有清洗步骤后,必须进行系统性的质量检查。我常用的检查清单包括:
count确认观测值数量符合预期assert验证关键逻辑关系tabstat查看主要变量分布stata复制// 自动化检查脚本
assert !missing(stkcd, year) // 关键变量无缺失
assert assets > 0 if !missing(assets) // 资产为正
tabstat assets, by(SOE) stats(mean sd n) // 分组统计
遇到问题时,可以逐步回溯操作步骤,用preserve和restore命令保护原始数据:
stata复制preserve
// 尝试性操作
restore // 还原数据
数据清洗是实证研究的基石。记得某次项目因为忽略了对母公司报表的过滤,导致所有结论都需要推倒重来。现在我的工作流程中一定会包含完整的检查环节,确保每个步骤都可靠无误。清洗后的数据最好保存为新的dta文件,并详细记录处理过程:
stata复制// 最终保存
label data "上市公司财务面板数据(2010-2020)"
notes: 数据清洗版本1.0,包含合并报表和产权性质虚拟变量
save clean_data.dta, replace