3. 数据清洗与预处理流程实现

数据清洗与预处理流程实现 学习卡片

任务说明

本案例面向健康管理PHM系统中的传感器采集数据,实现一条完整的数据清洗与预处理流水线。输入为包含时间戳、温度、振动幅值的原始CSV数据,输出为清洗后的标准数据集。需要处理缺失值(均值填充)、异常值(3σ准则剔除并插值)、重复值(按时间戳去重),并完成滑动平均平滑与中值滤波去噪。

数据清洗流程设计

整体处理链路为:读取原始数据 → 时间戳排序与去重 → 缺失值检测与均值填充 → 异常值检测(3σ)与线性插值修正 → 滑动平均平滑 → 中值滤波去噪 → 输出清洗结果。各步骤顺序固定,确保异常值修正不会因平滑而掩盖,去噪在最后执行以保留趋势特征。

数据清洗与预处理流水线 原始CSV读取 sensor_data.csv 时间戳排序 + 重复值删除 缺失值检测 均值填充 异常值检测 3σ准则 + 线性插值 滑动平均平滑 窗口=5 中值滤波去噪 窗口=3 质量统计 缺失/异常/重复计数 清洗结果输出 cleaned_data.csv 数据流方向

代码实现


import pandas as pd
import numpy as np

def load_data(filepath):
    """读取原始CSV,返回DataFrame"""
    df = pd.read_csv(filepath, parse_dates=['timestamp'])
    return df

def remove_duplicates(df):
    """按时间戳去重,保留第一条记录"""
    before = len(df)
    df = df.drop_duplicates(subset='timestamp', keep='first')
    df = df.sort_values('timestamp').reset_index(drop=True)
    dup_count = before - len(df)
    return df, dup_count

def fill_missing(df, columns):
    """缺失值用该列均值填充,返回填充数量"""
    missing_count = 0
    for col in columns:
        mask = df[col].isna()
        missing_count += mask.sum()
        df.loc[mask, col] = df[col].mean()
    return df, missing_count

def detect_outliers(df, columns, threshold=3):
    """3σ准则检测异常值,用线性插值修正"""
    outlier_count = 0
    for col in columns:
        mean = df[col].mean()
        std = df[col].std()
        if std == 0:
            continue
        mask = (np.abs(df[col] - mean) > threshold * std)
        outlier_count += mask.sum()
        # 对异常位置置NaN,然后线性插值
        df.loc[mask, col] = np.nan
        df[col] = df[col].interpolate(method='linear', limit_direction='both')
    return df, outlier_count

def smooth_data(df, columns, window=5):
    """滑动平均平滑"""
    df[columns] = df[columns].rolling(window=window, center=True, min_periods=1).mean()
    return df

def median_filter(df, columns, kernel=3):
    """中值滤波去噪"""
    df[columns] = df[columns].rolling(window=kernel, center=True, min_periods=1).median()
    return df

def preprocess_pipeline(input_path, output_path):
    """执行完整清洗流程"""
    df = load_data(input_path)
    value_cols = ['temperature', 'vibration']

    df, dup_count = remove_duplicates(df)
    df, miss_count = fill_missing(df, value_cols)
    df, out_count = detect_outliers(df, value_cols)
    df = smooth_data(df, value_cols, window=5)
    df = median_filter(df, value_cols, kernel=3)

    df.to_csv(output_path, index=False)

    stats = {
        'duplicates_removed': dup_count,
        'missing_filled': miss_count,
        'outliers_corrected': out_count,
        'total_records': len(df)
    }
    return stats

if __name__ == '__main__':
    # 生成样例数据(含缺失、异常、重复)
    np.random.seed(42)
    n = 100
    time_idx = pd.date_range('2024-01-01', periods=n, freq='min')
    temp = 25 + 5 * np.sin(np.linspace(0, 8, n)) + np.random.normal(0, 0.5, n)
    vib = 2.0 + 0.3 * np.cos(np.linspace(0, 6, n)) + np.random.normal(0, 0.1, n)

    # 注入1个重复时间戳
    time_idx = time_idx.insert(50, time_idx[50])
    temp = np.insert(temp, 50, temp[50])
    vib = np.insert(vib, 50, vib[50])

    # 注入3个缺失值
    temp[20] = np.nan
    vib[45] = np.nan
    temp[80] = np.nan

    # 注入2个异常值
    temp[30] = 45.0
    vib[70] = 8.0

    raw_df = pd.DataFrame({'timestamp': time_idx, 'temperature': temp, 'vibration': vib})
    raw_df.to_csv('sensor_data.csv', index=False)

    # 执行清洗
    stats = preprocess_pipeline('sensor_data.csv', 'cleaned_data.csv')
    print('清洗统计:', stats)
    print('清洗后数据预览:')
    print(pd.read_csv('cleaned_data.csv').head())

运行与验证

运行方式:将上述代码保存为 data_cleaning.py,在Python环境中执行 python data_cleaning.py。需要安装 pandas 和 numpy(pip install pandas numpy)。

验证方法:程序会生成 sensor_data.csv(含1个重复、3个缺失、2个异常)并输出清洗后的 cleaned_data.csv。控制台打印的统计信息应显示:duplicates_removed=1、missing_filled=3、outliers_corrected=2、total_records=100。检查输出文件:时间戳无重复且严格递增;温度列范围应在20~30之间(异常值45已被修正);振动列范围应在1.5~2.5之间(异常值8已被修正);无NaN值。

判定标准:统计计数与注入的污染数据完全一致,且清洗后数据范围符合物理合理区间,即可判定流程正确。若需验证其他数据,替换 sensor_data.csv 后重新运行即可。