
本文介绍在pandas中正确识别并替换以字符串形式“-9”开头的数值(如-9.0、-99.0)为nan的方法,重点解决因数据类型为数值型导致正则失效的问题,并提供类型转换、正则匹配与安全替换的完整实践方案。
本文介绍在pandas中正确识别并替换以字符串形式“-9”开头的数值(如-9.0、-99.0)为nan的方法,重点解决因数据类型为数值型导致正则失效的问题,并提供类型转换、正则匹配与安全替换的完整实践方案。
在处理气象、传感器或调查类数据时,常遇到用特殊数值(如 -9、-99、-999)表示缺失值的约定。但若原始DataFrame中相关列被Pandas自动解析为浮点型(float64)或整型(int64),直接对数值使用 replace(regex=...) 将完全无效——因为正则表达式仅作用于字符串,而数值类型不支持按“字符串前缀”匹配。
例如,-99.0 作为浮点数存储时,其底层是二进制数值,不包含字符 '-' 或 '9' 的文本结构,因此 regex='^-9.*' 无法命中。
✅ 正确做法分三步:
- 确认数据类型:先检查目标列的实际 dtype
- 统一转为字符串(可选但推荐):确保正则可生效
-
精准正则替换:使用
^锚定开头,匹配以-9起始的完整字符串
✅ 推荐解决方案(兼顾鲁棒性与可读性)
import pandas as pd
import numpy as np
# 方法一:对数值列单独处理(无需全局转str,更高效)
new_df = weatherData_original.copy()
# 定义需清洗的数值列(排除 'Date' 等非数值列)
numeric_cols = weatherData_original.select_dtypes(include=[np.number]).columns.tolist()
for col in numeric_cols:
# 将该列临时转为字符串,应用正则,再转回数值(NaN自动保留)
str_series = new_df[col].astype(str)
cleaned_str = str_series.replace(r'^-9.*', pd.NA, regex=True)
# 转回float,pd.NA会自动映射为np.nan(兼容老版本可写 np.nan)
new_df[col] = pd.to_numeric(cleaned_str, errors='coerce')
# 方法二:全局转str后批量替换(适合小数据或预处理阶段)
# df_str = weatherData_original.astype(str)
# new_df = df_str.replace(regex=r'^-9.*', value=pd.NA)
# # 注意:此时所有列均为str,需对数值列再次to_numeric()
? 关键说明与注意事项
- ❌
regex=r'^-9\d+'错误原因:\d+要求至少一个数字,但-9本身不匹配(无后续数字);且未覆盖-9.0、-99.00中的小数点。 - ❌
regex=r'^[-9].*'错误原因:[-9]是字符集,匹配“开头是-或9”,会错误替换9.5、-5.0等非目标值。 - ✅ 正确正则:
r'^-9.*'——^表示行首,-9字面匹配,.*匹配任意后续字符(包括.,0,9, 空等),精准覆盖-9、-9.0、-99.99、-9e2等全部情况。 - ⚠️
pd.NAvsnp.nan:Pandas 1.0+ 推荐用pd.NA(支持更多类型),但若下游依赖np.nan(如 matplotlib 绘图),最终可统一用new_df = new_df.replace(pd.NA, np.nan)。 - ? 建议在数据加载阶段即处理缺失码:使用
pd.read_csv(..., na_values=['-9', '-99', '-999']),避免后期清洗。
执行后,您的示例数据将变为:
Date Solar MaxRH AvgAirTemp 0 3/1/1983 <na><na><na> 1 3/2/1983 <na><na> 0.31 2 3/3/1983 <na><na><na> 3 3/4/1983 <na><na> 8.62 4 3/5/1983 19.97 64.6 8.91</na></na></na></na></na></na></na></na></na></na>
此方法确保语义准确、类型安全、性能可控,是清洗“伪缺失值编码”的标准实践。










