全部版块 我的主页
› 论坛 › 数据科学与人工智能 › 人工智能
283 0
2026-06-02

简介

时序特征工程的逻辑与表格数据完全不同:时序观测值并非相互独立、数据行的顺序至关重要,且最具价值的特征往往不是单一采样值,而是跨时间维度的变化规律——例如变化速率、滞后对比、滚动基线偏差等。

构建滞后特征、滑动窗口统计、多粒度时间分组,本质上都是有序序列的迭代处理问题。Python 内置的 itertools 模块是解决这类场景的最优工具。

它并非 pandas 中 .rolling() 等高层方法的替代品,而是提供了更底层、更灵活的搭建能力,支持开发者自定义完整特征逻辑、精准控制每一步运算。

本文将手把手教你用 itertools 搭建七大类核心时序特征,并基于统一样本数据集完成全部实战演示,所有代码已开源至GitHub。

一、构建实战样本数据集

在特征开发前,我们先创建一份模拟传感器时序数据集,包含温度、湿度、设备功耗三类核心指标,为一周(168小时)的逐小时采样数据。

import numpy as np
import pandas as pd
import itertools

np.random.seed(42)

# 时间维度:168小时(一周逐小时数据)
periods = 168
index = pd.date_range(start="2024-03-01", periods=periods, freq="h")
hours = np.arange(periods)

# 温度数据:日周期波动 + 缓慢趋势漂移 + 随机噪声
temp_base = 3.5
temp_daily = 1.2 * np.sin(2 * np.pi * hours / 24)
temp_drift = 0.003 * hours
temp_noise = np.random.normal(0, 0.3, periods)
temperature = temp_base + temp_daily + temp_drift + temp_noise

# 湿度数据:与温度负相关 + 随机噪声
humidity = 78 - 2.1 * (temperature - temp_base) + np.random.normal(0, 1.2, periods)

# 功耗数据:工作日高峰时段耗电更高、周末功耗降低
day_of_week = index.dayofweek
business_hours = ((index.hour >= 8) & (index.hour <= 18)).astype(int)
weekend_factor = np.where(day_of_week >= 5, 0.6, 1.0)
power = (
    42.0
    + 18.0 * business_hours * weekend_factor
    + np.random.normal(0, 2.1, periods)
)

# 构建数据集
df = pd.Datafr ame({
    "temperature_c": np.round(temperature, 3),
    "humidity_pct":  np.round(humidity, 2),
    "power_kw":      np.round(power, 2),
}, index=index)
df.index.name = "timestamp"

print(df.head(8))
print(f"\n数据集形状: {df.shape}")

运行输出:

temperature_c  humidity_pct  power_kw
timestamp
2024-03-01 00:00:00          3.649         77.39     40.27
2024-03-01 01:00:00          3.772         76.52     41.33
2024-03-01 02:00:00          4.300         75.25     42.87
2024-03-01 03:00:00          4.814         74.26     40.82
2024-03-01 04:00:00          4.481         75.85     40.27
2024-03-01 05:00:00          4.604         76.09     42.51
2024-03-01 06:00:00          5.192         74.78     42.51
2024-03-01 07:00:00          4.910         76.03     40.94

数据集形状: (168, 3)

我们最终得到168行3列的逐小时传感器时序数据,接下来基于该数据集开发各类时序特征。

二、基于 islice 生成滞后特征(Lag Features)

滞后特征是时序建模最基础的核心特征,代表指标在过去固定时间步的取值。例如1小时、6小时、24小时滞后值,可分别捕捉短期波动、日内周期规律、长期趋势与季节性特征。

我们使用 itertools.islice 高效截取序列,生成多尺度滞后特征:

sensor_readings = df["temperature_c"].tolist()
lag_offsets = [1, 6, 12, 24]  # 1/6/12/24小时滞后

lag_features = {}
for lag in lag_offsets:
    # 截取滞后序列,不生成完整列表副本,节省内存
    lagged = list(itertools.islice(sensor_readings, 0, len(sensor_readings) - lag))
    # 头部填充None,保证索引与原数据对齐
    lag_features[f"temp_lag_{lag}h"] = [None] * lag + lagged

# 构建滞后特征数据集
lag_df = pd.Datafr ame(lag_features, index=df.index)
lag_df["temperature_c"] = df["temperature_c"]

print(lag_df.iloc[24:30])

运行输出:

temp_lag_1h  temp_lag_6h  temp_lag_12h  temp_lag_24h  \
timestamp
2024-03-02 00:00:00        2.831        2.082         3.609         3.649
2024-03-02 01:00:00        3.409        1.974         2.654         3.772
2024-03-02 02:00:00        3.919        2.960         2.425         4.300
2024-03-02 03:00:00        3.833        2.647         2.528         4.814
2024-03-02 04:00:00        4.542        2.986         2.205         4.481
2024-03-02 05:00:00        4.443        2.831         2.486         4.604

                     temperature_c
timestamp
2024-03-02 00:00:00          3.409
2024-03-02 01:00:00          3.919
2024-03-02 02:00:00          3.833
2024-03-02 03:00:00          4.542
2024-03-02 04:00:00          4.443
2024-03-02 05:00:00          4.659

核心优势:islice 以迭代器方式截取序列,无需复制完整数据,内存效率极高;头部填充空值保证索引对齐,避免建模时数据错位。

三、基于 islice + accumulate 构建滚动窗口统计特征

单一滞后值仅能反映历史单点状态,而滚动窗口统计特征可以描述一段时间内的整体变化规律,是时序预测、异常检测的核心特征。

结合 islice 截取窗口数据、accumulate 计算累积和,高效实现6小时滚动均值、标准差、最值统计:

readings = df["temperature_c"].tolist()
window_size = 6  # 6小时滚动窗口

rolling_features = []

for i in range(len(readings)):
    # 窗口数据不足时填充空值
    if i < window_size:
        rolling_features.append({
            "rolling_mean_6h": None,
            "rolling_std_6h":  None,
            "rolling_min_6h":  None,
            "rolling_max_6h":  None,
        })
        continue

    # 截取当前窗口数据
    window = list(itertools.islice(readings, i - window_size, i))

    # 累积求和,单次遍历完成计算,提升效率
    running_sum = list(itertools.accumulate(window))
    window_mean = running_sum[-1] / window_size
    window_mean_sq = sum(x**2 for x in window) / window_size

    # 计算窗口统计量
    rolling_features.append({
        "rolling_mean_6h": round(window_mean, 4),
        "rolling_std_6h":  round((window_mean_sq - window_mean**2) ** 0.5, 4),
        "rolling_min_6h":  round(min(window), 4),
        "rolling_max_6h":  round(max(window), 4),
    })

roll_df = pd.Datafr ame(rolling_features, index=df.index)
roll_df["temperature_c"] = df["temperature_c"]

print(roll_df.iloc[6:12])

运行输出:

rolling_mean_6h  rolling_std_6h  rolling_min_6h  \
timestamp
2024-03-01 06:00:00           4.2700          0.4256           3.649
2024-03-01 07:00:00           4.5272          0.4386           3.772
2024-03-01 08:00:00           4.7168          0.2929           4.300
2024-03-01 09:00:00           4.7372          0.2662           4.422
2024-03-01 10:00:00           4.6912          0.2728           4.422
2024-03-01 11:00:00           4.6095          0.3769           3.991

                     rolling_max_6h  temperature_c
timestamp
2024-03-01 06:00:00           4.814          5.192
2024-03-01 07:00:00           5.192          4.910
2024-03-01 08:00:00           5.192          4.422
2024-03-01 09:00:00           5.192          4.538
2024-03-01 10:00:00           5.192          3.991
2024-03-01 11:00:00           5.192          3.704

核心优势:accumulate 单次遍历即可完成累积求和,无需重复调用 sum(),在流式大数据处理中可大幅提升运算效率。

四、基于 product 构建季节交互特征

多数时序数据存在多层级季节性叠加(时段、工作日/周末、峰谷时段),单一时间特征无法捕捉维度间的关联规律。利用 itertools.product 可生成全维度组合,构建季节交互基线特征,用于时序异常检测。

hours_of_day = list(range(24))
day_types = ["weekday", "weekend"]
operational_shifts = ["off_peak", "on_peak"]  # 高峰时段:8:00-18:00

# 生成所有时间维度组合网格
season_grid = list(itertools.product(hours_of_day, day_types, operational_shifts))
season_df = pd.Datafr ame(season_grid, columns=["hour", "day_type", "shift"])

# 模拟不同场景下的基准温度
np.random.seed(14)
season_df["baseline_temp_c"] = np.round(
    3.5
    + 0.8 * np.sin(2 * np.pi * season_df["hour"] / 24)
    + np.where(season_df["day_type"] == "weekend", 0.3, 0.0)
    + np.where(season_df["shift"] == "on_peak", 0.5, 0.0)
    + np.random.normal(0, 0.1, len(season_df)),
    3
)

print(season_df[season_df["hour"].isin([0, 8, 14, 20])].head(16).to_string(index=False))
print(f"\n总组合数量: {len(season_df)}")

运行输出:

hour day_type    shift  baseline_temp_c
   0  weekday off_peak            3.655
   0  weekday  on_peak            4.008
   0  weekend off_peak            3.817
   0  weekend  on_peak            4.293
   8  weekday off_peak            4.325
   8  weekday  on_peak            4.601
   8  weekend off_peak            4.446
   8  weekend  on_peak            4.978
  14  weekday off_peak            3.370
  14  weekday  on_peak            3.628
  14  weekend off_peak            3.279
  14  weekend  on_peak            3.959
  20  weekday off_peak            2.726
  20  weekday  on_peak            3.256
  20  weekend off_peak            3.056
  20  weekend  on_peak            3.530

总组合数量: 96

将该组合网格关联至原始数据集,可得到每一条采样数据的场景基准值,通过「实际值-基准值」计算偏差特征,精准捕捉异常波动。

五、基于 tee 实现并行窗口统计

实际场景中,我们常需要对同一窗口数据计算多项统计指标(均值、波动区间、变化速率)。itertools.tee 可基于同一个原始迭代器,生成多个独立子迭代器,避免重复遍历数据,大幅优化效率。

def sliding_window_stats(series, window_size):
    """基于tee实现滑动窗口多维度统计:均值、波动区间、变化速率"""
    results = []
    it = iter(series)

    # 初始化首个窗口
    window = list(itertools.islice(it, window_size))
    if len(window) < window_size:
        return results

    # 第一个窗口统计结果
    results.append({
        "window_mean":    round(sum(window) / window_size, 4),
        "window_range":   round(max(window) - min(window), 4),
        "rate_of_change": round(window[-1] - window[0], 4),
    })

    # 滑动窗口迭代更新
    for next_val in it:
        window = window[1:] + [next_val]
        # 生成两个独立迭代器,并行计算不同指标
        iter_a, iter_b = itertools.tee(iter(window))

        values_a = list(iter_a)
        values_b = list(iter_b)

        mean_val = sum(values_a) / window_size
        results.append({
            "window_mean":    round(mean_val, 4),
            "window_range":   round(max(values_b) - min(values_b), 4),
            "rate_of_change": round(window[-1] - window[0], 4),
        })

    return results

# 基于8小时窗口处理功耗数据
power_readings = df["power_kw"].tolist()
stats = sliding_window_stats(power_readings, window_size=8)

stats_df = pd.Datafr ame(stats, index=df.index[7:])
stats_df["power_kw"] = df["power_kw"].iloc[7:].values

print(stats_df.iloc[0:8])

运行输出:

window_mean  window_range  rate_of_change  power_kw
timestamp
2024-03-01 07:00:00      41.4400          2.60            0.67     40.94
2024-03-01 08:00:00      43.7825         18.74           17.68     59.01
2024-03-01 09:00:00      46.1775         20.22           17.62     60.49
2024-03-01 10:00:00      47.9387         20.22           16.14     56.96
2024-03-01 11:00:00      49.9663         20.22           16.77     57.04
2024-03-01 12:00:00      52.2437         19.55           15.98     58.49
2024-03-01 13:00:00      54.3738         19.55           17.04     59.55
2024-03-01 14:00:00      56.6412         19.71           19.71     60.65

六、基于 chain 组合多粒度时序特征

高质量时序特征往往需要融合多分辨率信息:原始瞬时值、短周期滚动统计、长周期滚动统计、时间日历特征。itertools.chain 可将多组特征列表无缝拼接,代码简洁易扩展。

humidity = df["humidity_pct"].tolist()

# 通用滚动均值计算函数
def rolling_means(series, window):
    means = []
    for i in range(len(series)):
        if i < window:
            means.append(None)
        else:
            w = list(itertools.islice(series, i - window, i))
            means.append(round(sum(w) / window, 3))
    return means

# 生成多粒度滚动特征
rolling_6h       = rolling_means(humidity, 6)
rolling_24h      = rolling_means(humidity, 24)
hour_of_day      = df.index.hour.tolist()
is_business_hour = [1 if 8 <= h <= 18 else 0 for h in hour_of_day]

# 链式拼接多类别特征名
feature_names = list(itertools.chain(
    ["humidity_raw"],
    ["humidity_roll_6h", "humidity_roll_24h"],
    ["hour_of_day", "is_business_hour"],
))

# 组装多分辨率特征数据集
multi_res_df = pd.Datafr ame({
    name: vals for name, vals in zip(
        feature_names,
        [humidity, rolling_6h, rolling_24h, hour_of_day, is_business_hour]
    )
}, index=df.index)

print(multi_res_df.iloc[24:30])

运行输出:

humidity_raw  humidity_roll_6h  humidity_roll_24h  \
timestamp
2024-03-02 00:00:00         78.45            79.622             78.055
2024-03-02 01:00:00         75.63            79.105             78.100
2024-03-02 02:00:00         77.51            78.190             78.062
2024-03-02 03:00:00         76.27            78.088             78.157
2024-03-02 04:00:00         74.96            77.805             78.240
2024-03-02 05:00:00         75.75            77.208             78.203

                     hour_of_day  is_business_hour
timestamp
2024-03-02 00:00:00            0                 0
2024-03-02 01:00:00            1                 0
2024-03-02 02:00:00            2                 0
2024-03-02 03:00:00            3                 0
2024-03-02 04:00:00            4                 0
2024-03-02 05:00:00            5                 0

七、基于 combinations 构建传感器 pairwise 时序相关性特征

多传感器时序数据中,指标间的动态关联关系比单一指标更具预测价值。利用 itertools.combinations 生成所有指标两两组合,计算窗口内动态相关系数,捕捉变量间联动规律。

sensor_cols = ["temperature_c", "humidity_pct", "power_kw"]
window_size = 12  # 12小时相关性窗口

pairwise_features = {}

# 遍历所有指标两两组合
for col_a, col_b in itertools.combinations(sensor_cols, 2):
    feature_name = f"corr_{col_a[:4]}_{col_b[:4]}_12h"
    correlations = []

    series_a = df[col_a].tolist()
    series_b = df[col_b].tolist()

    for i in range(len(series_a)):
        if i < window_size:
            correlations.append(None)
            continue

        # 截取窗口数据
        win_a = list(itertools.islice(series_a, i - window_size, i))
        win_b = list(itertools.islice(series_b, i - window_size, i))

        # 计算均值、协方差、标准差与相关系数
        mean_a = sum(win_a) / window_size
        mean_b = sum(win_b) / window_size

        cov   = sum((a - mean_a) * (b - mean_b) for a, b in zip(win_a, win_b)) / window_size
        std_a = (sum((a - mean_a)**2 for a in win_a) / window_size) ** 0.5
        std_b = (sum((b - mean_b)**2 for b in win_b) / window_size) ** 0.5

        corr = round(cov / (std_a * std_b), 4) if std_a > 0 and std_b > 0 else None
        correlations.append(corr)

    pairwise_features[feature_name] = correlations

corr_df = pd.Datafr ame(pairwise_features, index=df.index)
print(corr_df.iloc[12:18])

运行输出:

corr_temp_humi_12h  corr_temp_powe_12h  \
timestamp
2024-03-01 12:00:00             -0.6700             -0.2281
2024-03-01 13:00:00             -0.7208             -0.4960
2024-03-01 14:00:00             -0.7442             -0.6669
2024-03-01 15:00:00             -0.7678             -0.7076
2024-03-01 16:00:00             -0.8116             -0.7265
2024-03-01 17:00:00             -0.8368             -0.7482

                     corr_humi_powe_12h
timestamp
2024-03-01 12:00:00              0.5380
2024-03-01 13:00:00              0.6614
2024-03-01 14:00:00              0.7202
2024-03-01 15:00:00              0.7311
2024-03-01 16:00:00              0.7233
2024-03-01 17:00:00              0.7219

八、基于 accumulate 计算动态基线与偏差特征

时序数据的数值意义取决于相对历史基线的偏差。利用 itertools.accumulate 高效计算全局累积均值、历史最大值,实时生成动态基线与偏差特征,适用于趋势漂移检测、阈值超限识别。

readings = df["temperature_c"].tolist()

# 累积求和、累积计数,计算动态均值
running_sums   = list(itertools.accumulate(readings))
running_counts = list(itertools.accumulate([1] * len(readings)))
running_means  = [
    round(s / c, 4)
    for s, c in zip(running_sums, running_counts)
]

# 累积最大值(历史峰值)
running_max = list(itertools.accumulate(readings, func=max))

# 计算当前值与历史基线的偏差
deviation_from_baseline = [
    round(r - m, 4)
    for r, m in zip(readings, running_means)
]

# 组装基线特征数据集
baseline_df = pd.Datafr ame({
    "temperature_c":           readings,
    "running_mean":            running_means,
    "running_max":             running_max,
    "deviation_from_baseline": deviation_from_baseline,
}, index=df.index)

print(baseline_df.iloc[20:28])

运行输出:

temperature_c  running_mean  running_max  \
timestamp
2024-03-01 20:00:00          2.960        3.5857        5.192
2024-03-01 21:00:00          2.647        3.5430        5.192
2024-03-01 22:00:00          2.986        3.5188        5.192
2024-03-01 23:00:00          2.831        3.4902        5.192
2024-03-02 00:00:00          3.409        3.4869        5.192
2024-03-02 01:00:00          3.919        3.5035        5.192
2024-03-02 02:00:00          3.833        3.5157        5.192
2024-03-02 03:00:00          4.542        3.5524        5.192

                     deviation_from_baseline
timestamp
2024-03-01 20:00:00                  -0.6257
2024-03-01 21:00:00                  -0.8960
2024-03-01 22:00:00                  -0.5328
2024-03-01 23:00:00                  -0.6592
2024-03-02 00:00:00                  -0.0779
2024-03-02 01:00:00                   0.4155
2024-03-02 02:00:00                   0.3173
2024-03-02 03:00:00                   0.9896

九、全文总结:Itertools 时序特征工程对照表

时序特征工程的核心是挖掘数据的时间上下文信息,本文基于 itertools 七大核心函数,覆盖了工业界主流时序特征开发场景,所有方法均支持流式数据处理,适配大规模线上业务。

Itertools 函数 时序特征类型 实战示例
islice 滞后特征 1/6/24小时温度滞后值
islice + accumulate 滚动窗口统计特征 6小时窗口均值、标准差、最值
product 季节交互网格特征 时段×工作日×峰谷时段基准值
tee 并行窗口统计特征 窗口均值、波动区间、变化速率同步计算
chain 多粒度特征融合 原始值+滚动统计+时间特征组合
combinations 多指标两两相关性特征 温湿度、温功耗、湿功耗窗口相关系数
accumulate 动态基线与偏差特征 历史累积均值、峰值、实时偏差值

推荐学习书籍 《CDA一级教材》适合CDA一级考生备考,也适合业务及数据分析岗位的从业者提升自我。完整电子版已上线CDA网校,累计已有10万+在读~ !

免费加入阅读:https://edu.cda.cn/goods/show/3151?targetId=5147&preview=0

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群