4、数据清洗核心概念:缺失值、重复值、异常值、格式不一致、数据类型错误、时间序列问题
金融数据清洗是数据分析流程中最耗时、最影响结论可靠性的环节。金融数据往往来自行情接口、柜台系统、第三方数据库或手工录入,天然带有噪声。本章聚焦六大核心概念——缺失值、重复值、异常值、格式不一致、数据类型错误、时间序列问题,帮助零基础学员建立系统化的清洗认知框架。理解这些概念的本质、识别方法、处理策略和常见误区,是后续学习具体工具(如Python/Pandas、SQL)的基础。
上图展示了六大核心概念之间的关系与处理主线。它们并非孤立存在,例如格式不一致可能导致数据类型错误,异常值可能与时间序列中的跳变相关。实际清洗工作中,需要按“识别→诊断→处理→验证→记录”的闭环逻辑推进。下面逐一展开每个概念的原理、判断方法、实战案例与常见误区。
4.1 缺失值
核心原理
缺失值指数据集中某些字段的值为空(NULL、NaN、空字符串等)。金融数据中缺失值产生的原因包括:交易停牌导致行情缺失、手工录入遗漏、系统故障、数据源本身不完整等。缺失值会直接影响统计描述、回归分析和机器学习模型的训练效果,甚至导致模型偏差。
判断方法
- 直接查看:使用
df.info()或df.isnull().sum()快速统计每列缺失数量。 - 缺失模式分析:判断缺失是随机缺失(MCAR)、与观测值相关(MAR)还是非随机缺失(MNAR)。例如,某股票在停牌期间所有行情字段都缺失,属于结构性缺失。
- 缺失比例阈值:当某字段缺失超过30%时,通常不建议直接填充,需考虑删除或单独建模。
案例拆解:某券商客户风险评级数据
某券商客户风险测评数据中,“年收入”字段缺失率达25%,“投资经验年限”缺失率8%。直接删除缺失行会损失大量样本,而用均值填充“年收入”会严重扭曲分布(收入呈右偏)。实际操作中,采用分位数分组填充:按客户资产规模分5档,每档内用中位数填充“年收入”;“投资经验年限”则用多重插补法,结合年龄、职业等特征进行预测填充。处理后模型AUC从0.72提升至0.78。
常见误区
- 误区一:所有缺失值都用均值/中位数填充。对于时间序列数据,前向填充(ffill)或插值法往往更合理。
- 误区二:忽略缺失值产生的原因。例如,某字段缺失可能代表“无此业务”,而非“数据丢失”,此时应保留为特殊标记。
- 误区三:填充后不进行敏感性分析。应对比填充前后模型结果,确保结论稳健。
4.2 重复值
核心原理
重复值指数据集中存在完全一致或部分关键字段一致的多条记录。金融数据中重复值可能来自:数据源多次推送、多表合并时未去重、手工录入重复等。重复值会导致统计指标虚高、模型过拟合、交易成本计算错误。
判断方法
- 完全重复:所有字段完全一致,直接使用
df.duplicated()检测。 - 部分重复:基于业务主键判断,如“交易日期+证券代码+账户ID”唯一时,其他字段重复即为重复记录。
- 模糊重复:如客户姓名“张三”和“张 三”可能为同一人,需结合相似度算法(如编辑距离)判断。
案例拆解:银行交易流水去重
某银行内部审计时发现,某日交易流水表中有3.2%的记录重复。经排查,原因是核心系统与风控系统双写导致。去重策略:以“交易流水号+交易日期”为唯一键,保留最早一条记录,删除后续重复项。去重后交易总金额下降2.1%,审计差异消除。
常见误区
- 误区一:只做完全去重,忽略部分重复。应结合业务主键定义唯一性。
- 误区二:去重后不检查数据量变化。若去重比例异常(如超过10%),应回溯数据源。
- 误区三:去重时保留哪条记录随意选择。应明确规则,如保留最早、最新或数据质量最高的记录。
4.3 异常值
核心原理
异常值(离群点)指明显偏离正常分布的数据点。金融数据中异常值可能是真实的市场极端波动(如2015年A股千股跌停),也可能是数据录入错误(如将100元输成10000元)。区分真实异常与数据错误是清洗的关键。
判断方法
- 统计方法:3σ原则(均值±3倍标准差)、IQR(四分位距)法,适用于近似正态分布的数据。
- 业务规则:如股票日涨跌幅不超过±10%(主板),超过即为异常。
- 可视化方法:箱线图、散点图快速识别离群点。
- 模型方法:孤立森林、DBSCAN聚类等,适用于多维数据。
案例拆解:基金净值异常检测
某基金公司每日计算基金净值,某日发现某产品净值单日上涨15%,远超同类产品平均0.5%的波动。初步判断为异常值。排查过程:首先检查当日市场行情,确认无重大利好;其次检查估值系统日志,发现某重仓股价格源推送错误(将12.5元推送为125元)。修正价格后,净值恢复至正常水平。此案例说明,异常值处理必须结合业务背景,不能机械地删除或截尾。
常见误区
- 误区一:所有异常值都是错误数据。应结合业务场景判断。
- 误区二:用均值替换异常值。这会降低数据方差,影响风险度量。
- 误区三:只做单变量异常检测。多维异常(如价格与成交量同时异常)可能更有意义。
4.4 格式不一致
核心原理
格式不一致指同一字段在不同记录中呈现不同的表示形式。金融数据中常见于:日期格式(2024-01-01 vs 2024/1/1 vs 20240101)、货币单位(元 vs 万元 vs 美元)、证券代码(600000.SH vs 600000 vs 600000.SS)、文本大小写(ABC vs abc)等。格式不一致会导致数据无法直接合并、匹配和聚合。
判断方法
- 字段值域检查:使用
df['字段'].unique()查看所有唯一值,人工识别格式差异。 - 正则表达式匹配:如日期字段,用
\d{4}-\d{2}-\d{2}匹配标准格式,找出不匹配的记录。 - 长度检查:如证券代码应为6位数字,长度不符即为格式异常。
案例拆解:多源行情数据合并
某量化团队从Wind、Choice和交易所官网获取股票日行情。三个数据源的日期格式分别为“2024-01-01”、“2024/1/1”和“20240101”,证券代码分别为“600000.SH”、“600000”和“600000.SS”。合并前需统一格式:日期统一为YYYY-MM-DD,证券代码统一为“600000.SH”格式(交易所后缀大写)。处理后,三源数据可正常按日期和代码匹配,合并后数据量从单源的5000条增至15000条(含不同源交叉验证)。
常见误区
- 误区一:只统一显示格式,不统一存储格式。例如日期显示为“2024-01-01”但存储为字符串,无法进行时间运算。
- 误区二:忽略编码问题。如中文乱码、UTF-8与GBK混用。
- 误区三:格式统一后不验证。应抽样检查转换后的数据是否与原值等价。
4.5 数据类型错误
核心原理
数据类型错误指字段的存储类型与业务含义不符。金融数据中常见:数值字段存储为字符串(如“1,234.56”)、日期字段存储为字符串、布尔字段存储为0/1但被识别为整数等。数据类型错误会导致计算错误、排序异常、聚合结果偏差。
判断方法
- 使用
df.dtypes:检查每列的数据类型。 - 尝试转换:用
pd.to_numeric()、pd.to_datetime()尝试转换,观察是否报错或产生NaN。 - 业务逻辑验证:如“交易金额”字段出现负数,虽然类型为float,但业务上金额不应为负(除非是冲正记录)。
案例拆解:P2P平台逾期率计算错误
某P2P平台计算逾期率时,发现结果异常偏高。排查发现,“逾期天数”字段被存储为字符串类型,且部分值包含“天”字(如“15天”)。在计算逾期率时,字符串无法直接参与数值比较,导致所有非空值都被视为逾期。修复方法:提取字符串中的数字部分,转换为整数类型,再重新计算。修复后逾期率从45%降至8%,与业务实际相符。
常见误区
- 误区一:忽略“object”类型字段。object类型可能是字符串、混合类型或Python对象,需逐一检查。
- 误区二:强制转换导致数据丢失。如将“1,234.56”直接
astype(float)会报错,需先去除千分位逗号。 - 误区三:转换后不检查范围。如将日期字符串转换为datetime后,可能出现1900-01-01等异常值。
4.6 时间序列问题
核心原理
时间序列问题特指与时间索引相关的数据质量问题,包括:时间戳重复、时间间隔不规律、时区不一致、交易日历不匹配、时间戳精度不一致(秒级vs毫秒级)等。金融数据高度依赖时间顺序,时间序列问题会导致回测结果失真、信号延迟、风险指标计算错误。
判断方法
- 时间排序检查:确认时间戳是否严格递增。
- 频率检查:使用
df.index.to_series().diff()查看时间间隔分布,判断是否存在缺失时间点。 - 时区检查:确认所有时间戳是否在同一时区,或是否已标注时区信息。
- 交易日历匹配:金融数据应匹配交易所交易日历,非交易日的数据可能是错误或特殊事件。
案例拆解:高频交易回测时间对齐
某高频策略团队使用Level-2逐笔委托数据回测。原始数据时间戳为交易所服务器时间(UTC+8),但策略服务器使用UTC时间。直接回测导致所有信号延迟8小时,策略表现极差。修复方法:将时间戳统一转换为UTC+8,并重采样至毫秒级精度。同时发现,部分交易日数据存在时间戳重复(同一毫秒多条记录),按“接收序号”字段进行二次排序。修复后回测结果与实盘表现基本一致。
常见误区
- 误区一:忽略时区问题。跨境金融数据尤其需要注意,如美股数据使用美东时间,A股使用北京时间。
- 误区二:重采样时使用错误方法。如将日线数据重采样为周线时,应使用“最后交易日”而非“周五”作为周标签。
- 误区三:不处理时间戳精度不一致。如部分数据精确到秒,部分精确到毫秒,合并时需统一精度。
4.7 六大概念综合对比与清洗流程
| 概念 | 典型表现 | 识别方法 | 常用处理策略 | 金融场景示例 |
|---|---|---|---|---|
| 缺失值 | 字段为空、NaN | isnull()统计、缺失模式分析 | 删除、填充(均值/中位数/前向)、插值、多重插补 | 停牌股票行情缺失 |
| 重复值 | 完全重复或主键重复 | duplicated()、业务主键检查 | 删除重复项、保留指定记录 | 多系统双写导致流水重复 |
| 异常值 | 偏离分布、超出业务范围 | 3σ、IQR、箱线图、业务规则 | 修正、截尾、标记保留 | 价格源推送错误导致净值跳变 |
| 格式不一致 | 日期/代码/单位表示多样 | unique()值域检查、正则匹配 | 统一格式、标准化映射 | 多源行情数据合并 |
| 数据类型错误 | 数值存为字符串、日期存为文本 | dtypes检查、尝试转换 | 类型转换、提取数字、解析日期 | 逾期天数含“天”字导致计算错误 |
| 时间序列问题 | 时间戳重复、时区不一致、频率不规律 | diff()间隔检查、时区核对 | 排序、重采样、时区转换、日历匹配 | 高频回测时间偏移8小时 |
综合来看,六大概念在实际数据中往往交织出现。例如,格式不一致可能导致数据类型错误,异常值检测时需先排除缺失值干扰。建议清洗流程遵循以下顺序:先处理缺失值(确定删除或填充策略),再处理重复值(去重),然后检查数据类型并统一格式,接着进行异常值检测与处理,最后专门处理时间序列问题。每一步处理后都应输出清洗报告,记录处理前后数据量、关键字段统计量变化,确保清洗过程可追溯、可复现。