在Python DataFrame中计算趋势的连续累积频次及滚动平均趋势长度的实现方法
在Python DataFrame中计算趋势的连续累积频次及滚动平均趋势长度的实现方法
嘿,这个需求在处理股票时间序列数据时挺常见的,我来给你一步步拆解实现思路和代码,完全用pandas就能搞定~
一、实现连续累积频次(Count列)
核心思路是先识别趋势的分界点,再对每个连续趋势组进行计数。具体步骤如下:
- 首先构造你的示例DataFrame(方便测试):
import pandas as pd data = { 'Date': ['1/1', '2/1', '3/1', '4/1', '5/1'], 'Price': [110, 108, 106, 112, 116], 'Supertrend': [-1, -1, -1, 1, 1] } df = pd.DataFrame(data)
- 生成趋势分组标签:
我们通过对比当前行和上一行的Supertrend值,判断是否进入新趋势,再用cumsum()生成唯一的组编号:
# 标记当前行与上一行趋势是否不同,首次行无前置值,默认是新组 df['Trend_Group'] = (df['Supertrend'] != df['Supertrend'].shift(1)).cumsum()
- 计算连续累积频次:
按Trend_Group分组后,用cumcount()统计每组内的行位置,加1就是连续次数:
df['Count'] = df.groupby('Trend_Group').cumcount() + 1
执行完后,你的DataFrame就会和示例的结果完全一致:
| Date | Price | Supertrend | Trend_Group | Count |
|---|---|---|---|---|
| 1/1 | 110 | -1 | 1 | 1 |
| 2/1 | 108 | -1 | 1 | 2 |
| 3/1 | 106 | -1 | 1 | 3 |
| 4/1 | 112 | 1 | 2 | 1 |
| 5/1 | 116 | 1 | 2 | 2 |
如果需要把Count作为数组添加到原DataFrame,直接取df['Count'].values即可。
二、计算滚动平均趋势长度
这里分两种场景:已结束趋势的滚动平均和包含当前未结束趋势的滚动平均,我主要讲更实用的前者(因为未结束趋势的长度还在变化,平均意义不大):
- 先统计每个趋势的长度:
# 按趋势分组,统计每组的行数(即趋势长度) trend_lengths = df.groupby('Trend_Group').size().reset_index(name='Trend_Length')
- 计算滚动平均:
用expanding().mean()计算从第一个趋势到当前趋势的平均长度:
trend_lengths['Rolling_Mean'] = trend_lengths['Trend_Length'].expanding().mean()
此时trend_lengths的结果是:
| Trend_Group | Trend_Length | Rolling_Mean |
|---|---|---|
| 1 | 3 | 3.0 |
| 2 | 2 | 2.5 |
- 把滚动平均映射回原DataFrame:
如果需要让原DataFrame的每一行都对应到当前趋势所属的滚动平均(当前未结束趋势用最近的已结束平均填充):
# 合并趋势长度和滚动平均到原DataFrame df = df.merge(trend_lengths[['Trend_Group', 'Rolling_Mean']], on='Trend_Group', how='left') # 对于未结束的趋势(比如后续新增的行),用前一个趋势的滚动平均填充 df['Rolling_Mean'] = df['Rolling_Mean'].ffill()
最终原DataFrame会新增Rolling_Mean列,每一行都能看到到当前趋势为止的平均趋势长度。
如果需要把这个滚动平均作为数组,取df['Rolling_Mean'].values即可。
备注:内容来源于stack exchange,提问作者SplooshM
相关产品推荐
相关产品推荐

