脚本怎样清洗异常数据

wen 实用脚本 34

本文目录导读:

脚本怎样清洗异常数据

  1. 前置准备
  2. 场景一:处理缺失值
  3. 场景二:处理重复数据
  4. 场景三:处理格式异常/类型错误
  5. 场景四:处理逻辑异常/离群值
  6. 场景五:处理不一致数据
  7. 完整脚本示例
  8. 其他环境的脚本工具
  9. 总结建议

清洗异常数据是数据预处理中非常关键的一步,具体用什么脚本,取决于你的数据格式(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')

处理缺失值

异常定义NaNnull、空字符串、特定占位符(如 "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 (命令行):适用于大型文本文件,用 sedawkgrep 快速处理行级异常。
    # 删除包含空值的行(假设CSV格式)
    grep -v ',,,' data.csv > clean.csv
    # 替换特定字符串
    sed -i 's/未知/N\/A/g' data.csv

总结建议

  1. 一定要备份原始数据(不要直接在原文件上修改)。
  2. 检查清洗后的结果df_cleaned.info()df_cleaned.describe() 会很有用。
  3. 异常处理策略因业务而异:年龄可以是 150 岁(在某些特殊行业),也可以是异常值。先理解业务,再写规则

如果你能提供具体的数据样本(几行带异常的数据)和预期处理逻辑,我可以为你生成更针对性的脚本。

抱歉,评论功能暂时关闭!