本文目录导读:

清洗异常数据是数据预处理中非常关键的一步,具体用什么脚本,取决于你的数据格式(CSV、JSON、数据库等)和编程环境(Python、SQL、Shell等)。
Python 是目前最常用、最灵活的数据清洗工具(尤其是配合 Pandas 库)。
以下是几种常见异常数据场景及其对应的 Python 脚本模式,你可以根据实际情况组合使用:
前置准备
你需要安装并导入 Pandas 库。
import pandas as pd
import numpy as np
# 读取数据(以 CSV 为例)
df = pd.read_csv('your_data.csv')
# 或者读取 Excel
# df = pd.read_excel('your_data.xlsx')
处理缺失值
异常定义:NaN、null、空字符串、特定占位符(如 "N/A"、"未知")。
脚本方案:
# 1. 查看缺失值分布
print(df.isnull().sum())
# 2. 删除包含缺失值的行(如果缺失比例较小)
df_cleaned = df.dropna()
# 3. 删除特定列有缺失的行
df_cleaned = df.dropna(subset=['重要列名1', '重要列名2'])
# 4. 填充缺失值(常用策略)
# 用均值填充(数值列)
df['年龄'] = df['年龄'].fillna(df['年龄'].mean())
# 用中位数填充(数值列,有异常值时比均值更鲁棒)
df['收入'] = df['收入'].fillna(df['收入'].median())
# 用众数填充(类别列)
df['性别'] = df['性别'].fillna(df['性别'].mode()[0])
# 用前一个有效值填充(时间序列)
df['价格'] = df['价格'].fillna(method='ffill')
# 或标记为 "未知"
df['城市'] = df['城市'].fillna('未知')
处理重复数据
异常定义:完全相同的行,或某些关键列重复。
脚本方案:
# 1. 查看重复行数量 print(df.duplicated().sum()) # 2. 删除完全重复的行(只保留第一个) df_cleaned = df.drop_duplicates() # 3. 基于特定列去重(同一ID只保留第一条记录) df_cleaned = df.drop_duplicates(subset=['用户ID'], keep='first') # keep='last' 保留最后一条
处理格式异常/类型错误
异常定义:数值列里混入了字符串(如 "100元"、"N/A")、日期格式不统一。
脚本方案:
# 1. 强制转换数值列,无法转换的设为 NaN df['价格'] = pd.to_numeric(df['价格'], errors='coerce') # errors='coerce' 将 "100元" 这种变成 NaN # 2. 统一日期格式 df['日期'] = pd.to_datetime(df['日期'], format='mixed', errors='coerce') # 解析失败会变成 NaT(缺失时间) # 3. 字符串清洗(去空格、转小写、替换特殊字符) df['姓名'] = df['姓名'].str.strip() # 去除前后空格 df['邮箱'] = df['邮箱'].str.lower() # 统一小写 df['手机号'] = df['手机号'].str.replace(r'\D', '', regex=True) # 只保留数字
处理逻辑异常/离群值
异常定义:年龄为 200 岁、月收入为负数、值远超合理范围(3σ 之外或 IQR 区间外)。
脚本方案:
# 1. 基于业务规则直接过滤 df_cleaned = df[(df['年龄'] > 0) & (df['年龄'] < 120)] df_cleaned = df[df['月收入'] >= 0] # 2. 使用 Z-score 方法(基于标准差,适用于近似正态分布数据) from scipy import stats z_scores = np.abs(stats.zscore(df['数值列'])) df_cleaned = df[z_scores < 3] # 保留 Z-score 小于 3 的数据 # 3. 使用 IQR(四分位距)方法(对异常值更鲁棒) Q1 = df['数值列'].quantile(0.25) Q3 = df['数值列'].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR df_cleaned = df[(df['数值列'] >= lower_bound) & (df['数值列'] <= upper_bound)]
处理不一致数据
异常定义:同一个概念有多种写法(如 "北京"、"bj"、"北京市")。
脚本方案:
# 1. 替换映射
city_map = {
'北京': '北京市', 'bj': '北京市', 'BJS': '北京市',
'上海': '上海市', 'sh': '上海市'
}
df['城市'] = df['城市'].replace(city_map)
# 2. 使用模糊匹配(需要 fuzzywuzzy 等库)
# 将相似度低的留作待审查
完整脚本示例
import pandas as pd
import numpy as np
def clean_data(df):
"""通用的异常数据清洗函数"""
# 复制原始数据,避免修改原数据
df_clean = df.copy()
# 1. 处理缺失值
df_clean['数值列'] = pd.to_numeric(df_clean['数值列'], errors='coerce')
df_clean['数值列'] = df_clean['数值列'].fillna(df_clean['数值列'].median())
# 2. 处理重复项
df_clean = df_clean.drop_duplicates(subset=['唯一ID列'], keep='last')
# 3. 处理逻辑异常
df_clean = df_clean[(df_clean['年龄'] >= 0) & (df_clean['年龄'] <= 120)]
# 4. 统一字符串格式
df_clean['城市'] = df_clean['城市'].str.strip().str.upper()
# 5. 重置索引
df_clean = df_clean.reset_index(drop=True)
return df_clean
# 使用
df_cleaned = clean_data(df)
df_cleaned.to_csv('cleaned_data.csv', index=False)
print("清洗完成!")
其他环境的脚本工具
- SQL:如果你在使用数据库,
WHERE过滤 +UPDATE替换 是做清洗的传统方式。-- 删除异常行 DELETE FROM table_name WHERE age < 0 OR age > 120; -- 更新缺失值 UPDATE table_name SET city = '未知' WHERE city IS NULL OR city = '';
- Shell (命令行):适用于大型文本文件,用
sed、awk、grep快速处理行级异常。# 删除包含空值的行(假设CSV格式) grep -v ',,,' data.csv > clean.csv # 替换特定字符串 sed -i 's/未知/N\/A/g' data.csv
总结建议
- 一定要备份原始数据(不要直接在原文件上修改)。
- 检查清洗后的结果:
df_cleaned.info()和df_cleaned.describe()会很有用。 - 异常处理策略因业务而异:年龄可以是 150 岁(在某些特殊行业),也可以是异常值。先理解业务,再写规则。
如果你能提供具体的数据样本(几行带异常的数据)和预期处理逻辑,我可以为你生成更针对性的脚本。