
本文介绍如何在 Pandas 中按时间顺序(DateTime)对数值列(Qty)进行条件分组累计求和:为 Tag ≠ 2 的记录计算运行总量(RBQ),为 Tag == 2 的记录单独计算运行总量(RSQ),确保结果严格遵循时间先后逻辑。
本文介绍如何在 pandas 中按时间顺序(datetime)对数值列(qty)进行条件分组累计求和:为 `tag ≠ 2` 的记录计算运行总量(rbq),为 `tag == 2` 的记录单独计算运行总量(rsq),确保结果严格遵循时间先后逻辑。
在数据分析中,常需根据业务规则对时间序列数据进行条件性、有序的累计统计。例如,本例要求:
- 新增列
RBQ:截至当前行DateTime时间点,所有Tag != 2行的Qty累加值(含当前行); - 新增列
RSQ:截至当前行DateTime时间点,所有Tag == 2行的Qty累加值(含当前行);
⚠️ 关键前提:累计必须严格按DateTime升序执行,而非原始行序——否则结果将错乱(如示例中2025-02-02行若排在开头,其 RBQ 就会错误包含后续所有非 Tag=2 的值)。
✅ 正确实现步骤(推荐方案)
首先确保 DateTime 列为 datetime64 类型并按时间排序:
import pandas as pd
# 示例数据(注意:DateTime 需转为 datetime 类型)
df = pd.DataFrame({
'DateTime': pd.to_datetime([
'2025-01-01 13:00', '2025-01-03 13:22',
'2025-01-10 12:33', '2025-01-22 10:04',
'2025-01-29 09:30', '2025-02-02 15:05'
]),
'Tag': [1, 1, 2, 2, 3, 1],
'Qty': [270, 32, 44, 120, 182, 216]
})
# ⚠️ 核心:必须先按 DateTime 排序,再计算累积量
df_sorted = df.sort_values('DateTime').reset_index(drop=True)
cond = df_sorted['Tag'] == 2
# 分别构造两个条件序列:非 Tag=2 → 保留 Qty,否则置 0;Tag=2 → 保留 Qty,否则置 0
df_sorted['RBQ'] = df_sorted['Qty'].where(~cond, 0).cumsum()
df_sorted['RSQ'] = df_sorted['Qty'].where(cond, 0).cumsum()
# 若需恢复原始顺序(可选),可用 merge 或 map 回原 df
result = df.merge(df_sorted[['DateTime', 'RBQ', 'RSQ']], on='DateTime', how='left')
print(result)输出结果完全匹配目标表:
| DateTime | Tag | Qty | RBQ | RSQ |
|---|---|---|---|---|
| 2025-01-01 13:00 | 1 | 270 | 270 | 0 |
| 2025-01-03 13:22 | 1 | 32 | 302 | 0 |
| 2025-01-10 12:33 | 2 | 44 | 302 | 44 |
| 2025-01-22 10:04 | 2 | 120 | 302 | 164 |
| 2025-01-29 09:30 | 3 | 182 | 484 | 164 |
| 2025-02-02 15:05 | 1 | 216 | 700 | 164 |
? 提示:
where(~cond, 0)等价于mask(cond, 0),语义更清晰——“仅当不满足条件时保留原值,否则填 0”。
? 替代方案:透视 + 累积(适合多条件扩展)
若未来需支持更多 Tag 分组(如 Tag==1, Tag==2, Tag==3 各自独立累计),推荐使用 pivot 方式,更具可扩展性:
# 构造分组标识列
df_pivot = df_sorted.assign(
group_col=df_sorted['Tag'].map({2: 'RSQ', 1: 'RBQ', 3: 'RBQ'}) # 可灵活映射
)
# 透视后累积,再合并回原表
cum_pivot = df_pivot.pivot(columns='group_col', values='Qty').fillna(0).cumsum()
result_pivot = df_sorted.join(cum_pivot, rsuffix='_cum').fillna(0)⚠️ 常见错误与注意事项
-
忽略排序:直接在未排序的 DataFrame 上
cumsum()会导致 RBQ/RSQ 按输入顺序累加,违背“截至当前时间点”的业务含义; -
混淆布尔逻辑:
df['Tag'].eq(2)返回True/False,注意~cond表示Tag != 2; -
索引错位风险:若用
sort_values()后未reset_index(),再merge时可能因索引不一致导致错行; -
空值处理:若
Qty存在 NaN,建议提前fillna(0),避免cumsum()传播 NaN。
✅ 总结
实现条件性时间累计求和的核心三步:
-
标准化时间列:
pd.to_datetime()+sort_values('DateTime'); -
构造条件掩码:用
where()/mask()生成按条件过滤的数值序列; -
应用累积函数:对掩码后序列调用
.cumsum(),确保时间序贯性。
该模式可轻松泛化至多标签、多指标、滑动窗口等场景,是 Pandas 时间序列分析中的基础而关键的技能。

















