
时序特征工程的逻辑与表格数据完全不同:时序观测值并非相互独立、数据行的顺序至关重要,且最具价值的特征往往不是单一采样值,而是跨时间维度的变化规律——例如变化速率、滞后对比、滚动基线偏差等。
构建滞后特征、滑动窗口统计、多粒度时间分组,本质上都是有序序列的迭代处理问题。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列的逐小时传感器时序数据,接下来基于该数据集开发各类时序特征。
滞后特征是时序建模最基础的核心特征,代表指标在过去固定时间步的取值。例如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 计算累积和,高效实现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(),在流式大数据处理中可大幅提升运算效率。
多数时序数据存在多层级季节性叠加(时段、工作日/周末、峰谷时段),单一时间特征无法捕捉维度间的关联规律。利用 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
将该组合网格关联至原始数据集,可得到每一条采样数据的场景基准值,通过「实际值-基准值」计算偏差特征,精准捕捉异常波动。
实际场景中,我们常需要对同一窗口数据计算多项统计指标(均值、波动区间、变化速率)。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
高质量时序特征往往需要融合多分辨率信息:原始瞬时值、短周期滚动统计、长周期滚动统计、时间日历特征。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
多传感器时序数据中,指标间的动态关联关系比单一指标更具预测价值。利用 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
时序数据的数值意义取决于相对历史基线的偏差。利用 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 函数 | 时序特征类型 | 实战示例 |
|---|---|---|
| islice | 滞后特征 | 1/6/24小时温度滞后值 |
| islice + accumulate | 滚动窗口统计特征 | 6小时窗口均值、标准差、最值 |
| product | 季节交互网格特征 | 时段×工作日×峰谷时段基准值 |
| tee | 并行窗口统计特征 | 窗口均值、波动区间、变化速率同步计算 |
| chain | 多粒度特征融合 | 原始值+滚动统计+时间特征组合 |
| combinations | 多指标两两相关性特征 | 温湿度、温功耗、湿功耗窗口相关系数 |
| accumulate | 动态基线与偏差特征 | 历史累积均值、峰值、实时偏差值 |

扫码加好友,拉您进群



收藏
