Pandas如何基于Trend列统计DataFrame涨跌趋势块数量
连续趋势块编号与统计实现
原始数据结构
SMA数据存储在pandas DataFrame中,样例数据如下:
Date SMA_50 SMA_200 Trend Trend CumCount T 2019-09-24 35.559013 38.942979 Down 1 2019-09-25 35.427135 38.904934 Down 2 2019-09-26 35.295066 38.864042 Down 3 2019-09-27 35.165275 38.827087 Down 4 2019-09-30 35.035484 38.788046 Down 5 2020-08-31 34.697343 34.689469 Up 1 2020-09-01 34.768881 34.691034 Up 2 2020-09-02 34.852941 34.690655 Up 3 2020-09-03 34.932827 34.686765 Up 4 2020-09-04 35.009488 34.680598 Up 5 2020-09-08 35.083302 34.675285 Up 6 2020-09-09 35.150474 34.667884 Up 7 2019-10-01 34.895256 38.744687 Down 1 2019-10-02 34.736053 38.701518 Down 2 2019-10-03 34.594877 38.665180 Down 3 2019-10-04 34.466983 38.634488 Down 4 2019-10-07 34.329222 38.605361 Down 5
字段说明:
Date:行情日期SMA_50:50周期简单移动平均线数值SMA_200:200周期简单移动平均线数值Trend:当前趋势标识,取值为Up(上涨)、Down(下跌)Trend CumCount:单段连续趋势内的行累计计数,每段新趋势的第一行该值为1
目标效果
新增T列,对每一段连续的同趋势块按类型独立编号,同一段趋势内所有行的T值保持一致,处理后结果如下:
Date SMA_50 SMA_200 Trend Trend CumCount T 2019-09-24 35.559013 38.942979 Down 1 1 2019-09-25 35.427135 38.904934 Down 2 1 2019-09-26 35.295066 38.864042 Down 3 1 2019-09-27 35.165275 38.827087 Down 4 1 2019-09-30 35.035484 38.788046 Down 5 1 2020-08-31 34.697343 34.689469 Up 1 1 2020-09-01 34.768881 34.691034 Up 2 1 2020-09-02 34.852941 34.690655 Up 3 1 2020-09-03 34.932827 34.686765 Up 4 1 2020-09-04 35.009488 34.680598 Up 5 1 2020-09-08 35.083302 34.675285 Up 6 1 2020-09-09 35.150474 34.667884 Up 7 1 2019-10-01 34.895256 38.744687 Down 1 2 2019-10-02 34.736053 38.701518 Down 2 2 2019-10-03 34.594877 38.665180 Down 3 2 2019-10-04 34.466983 38.634488 Down 4 2 2019-10-07 34.329222 38.605361 Down 5 2
同时需要统计上涨、下跌趋势块各自的出现次数。
实现代码
假设DataFrame变量名为df,按以下步骤操作即可。
1. 生成T列
两种实现方式可选:
- 方式1:依赖已有的
Trend CumCount列,逻辑简单运行快
# 标记新趋势块的起点(CumCount=1即为新块第一行) df['is_new_block'] = df['Trend CumCount'] == 1 # 按趋势类型分组,对新块标记累计求和得到同类型下的块编号 df['T'] = df.groupby('Trend')['is_new_block'].cumsum().astype(int) # 删除临时列 df.drop(columns=['is_new_block'], inplace=True)
- 方式2:不依赖
Trend CumCount列,直接通过相邻行的Trend值变化识别块,鲁棒性更强
# 先给全局所有连续同趋势块分配唯一ID df['global_block_id'] = (df['Trend'] != df['Trend'].shift()).cumsum() # 按趋势类型分组,给同类型下的不同块依次编号 df['T'] = df.groupby('Trend')['global_block_id'].transform( lambda x: x.ne(x.shift()).cumsum() ).astype(int) # 删除临时列 df.drop(columns=['global_block_id'], inplace=True)
2. 统计两类趋势块的数量
每个趋势块对应唯一的(Trend, T)组合,去重后计数即可:
block_stats = df[['Trend', 'T']].drop_duplicates()['Trend'].value_counts()
针对示例数据,运行后输出结果为:
Down 2 Up 1 Name: Trend, dtype: int64
即下跌趋势块共2个,上涨趋势块共1个,和实际数据匹配。
内容的提问来源于stack exchange,提问作者antobzzll
相关产品推荐
相关产品推荐

