4. 处理缺失值

任务说明

本案例处理时间序列数据中的缺失值,采用前向填充(ffill)与后向填充(bfill)两种策略。输入为一组带时间戳的观测序列,其中部分时间点数据缺失;目标是生成两个完整序列:一个用最近的有效观测值向后填充(前向填充),另一个用下一个有效观测值向前填充(后向填充),并输出填充结果供下游分析使用。

数据与依赖

使用Python标准库csv与datetime实现,不依赖第三方库。输入文件sensor_data.csv包含两列:timestamp(ISO格式)与value(浮点数,缺失为空字符串)。样例数据如下:

timestamp,value
2025-01-01 00:00:00,21.5
2025-01-01 00:01:00,
2025-01-01 00:02:00,
2025-01-01 00:03:00,22.1
2025-01-01 00:04:00,
2025-01-01 00:05:00,21.9

实现代码

import csv
from datetime import datetime

def load_data(path):
    rows = []
    with open(path, newline='', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for r in reader:
            ts = datetime.strptime(r['timestamp'], '%Y-%m-%d %H:%M:%S')
            val_str = r['value'].strip()
            val = float(val_str) if val_str else None
            rows.append({'ts': ts, 'val': val})
    return rows

def fill_missing(rows):
    ffill = []
    bfill = []
    last_valid = None
    n = len(rows)

    # 前向填充:用前一个有效值填充
    for r in rows:
        if r['val'] is not None:
            last_valid = r['val']
        ffill.append(last_valid)

    # 后向填充:用后一个有效值填充
    next_valid = None
    for i in range(n - 1, -1, -1):
        if rows[i]['val'] is not None:
            next_valid = rows[i]['val']
        bfill.insert(0, next_valid)

    return ffill, bfill

def write_output(path, rows, ffill, bfill):
    with open(path, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(['timestamp', 'original', 'ffill', 'bfill'])
        for i, r in enumerate(rows):
            orig = '' if r['val'] is None else f"{r['val']:.1f}"
            ff = '' if ffill[i] is None else f"{ffill[i]:.1f}"
            bf = '' if bfill[i] is None else f"{bfill[i]:.1f}"
            writer.writerow([r['ts'].strftime('%Y-%m-%d %H:%M:%S'), orig, ff, bf])

if __name__ == '__main__':
    data = load_data('sensor_data.csv')
    ff, bf = fill_missing(data)
    write_output('filled_output.csv', data, ff, bf)
    print("处理完成,结果已写入 filled_output.csv")

运行与验证

将上述代码保存为fill_missing.py,与sensor_data.csv置于同一目录,执行:

python fill_missing.py

程序读取输入文件,对缺失值分别执行前向与后向填充,将结果写入filled_output.csv。验证方法:打开输出文件,检查每个缺失位置——ffill列应等于该位置之前最近的非空值;bfill列应等于该位置之后最近的非空值。若序列开头无前值,则ffill为空;若结尾无后值,则bfill为空。

针对样例输入,预期输出文件内容如下(确定性推导结果):

timestamp,original,ffill,bfill
2025-01-01 00:00:00,21.5,21.5,21.5
2025-01-01 00:01:00,,21.5,22.1
2025-01-01 00:02:00,,21.5,22.1
2025-01-01 00:03:00,22.1,22.1,22.1
2025-01-01 00:04:00,,22.1,21.9
2025-01-01 00:05:00,21.9,21.9,21.9

判定标准:输出文件与上述逐行一致,且程序无异常退出,即视为通过。

缺失值填充处理流程 sensor_data.csv 时间戳 + 原始值 解析与检测 识别 None 缺失位 前向填充 (ffill) 用前一个有效值 后向填充 (bfill) 用后一个有效值 filled_output.csv 原始+ffill+bfill 样例数据填充示意 时间 原始值 ffill bfill 00:0021.521.521.5 00:01—21.522.1 00:02—21.522.1 00:0322.122.122.1