如何处理时间序列DataFrame的H/L集群,筛选极值生成交替序列?
问题描述
我有如下时间序列DataFrame:
| Val1 | Val2 | H | L |
|---|---|---|---|
| 244.2 | 233.05 | H | None |
| 261.2 | 252.8 | H | None |
| 242.35 | 235.8 | H | None |
| 251.1 | 244.55 | H | None |
| 244.5 | 239.55 | None | L |
| 271.25 | 262.55 | H | None |
| 274 | 270.45 | H | None |
| 245.05 | 236.65 | None | L |
| 243.35 | 237.55 | None | L |
| 255.7 | 251.55 | H | None |
| 248.8 | 243.2 | None | L |
| 283.75 | 272.15 | H | None |
| 269.45 | 262.7 | None | L |
| 260.6 | 254.6 | H | None |
| 285 | 275 | None | L |
| 272.5 | 265.35 | None | L |
| 267 | 254.85 | None | L |
| 256.65 | 253.5 | None | L |
| 268 | 257.75 | H | None |
| 272.1 | 266.75 | H | None |
| 281.45 | 272.85 | None | L |
| 288.75 | 282.05 | H | None |
| 268.75 | 264.5 | None | L |
| 283 | 275.75 | None | L |
| 285.95 | 278.15 | H | None |
| 271.35 | 265.2 | None | L |
| 308.15 | 300 | H | None |
| 312.85 | 304.7 | H | None |
| 311.55 | 302.2 | None | L |
| 327.4 | 318.65 | H | None |
| 327 | 319.5 | H | None |
| 318.7 | 313.9 | None | L |
| 293.1 | 283.45 | None | L |
| 306 | 301.5 | H | None |
| 303.9 | 296.2 | None | L |
| 293.4 | 261.55 | None | L |
| 302.8 | 298.1 | H | None |
| 293.7 | 289.05 | None | L |
| 267.95 | 264.05 | None | L |
| 276.55 | 273.2 | H | None |
| 268.15 | 255 | None | L |
| 314 | 303.9 | None | L |
| 324.2 | 311.05 | H | None |
| 332.35 | 323.8 | H | None |
| 312.35 | 306.3 | H | None |
| 308.4 | 300.2 | None | L |
| 312.5 | 308.55 | None | L |
| 365.7 | 355.6 | H | None |
| 334 | 318.8 | H | None |
| 319.3 | 313.95 | None | L |
| 327.8 | 323.15 | H | None |
我需要生成H与L值交替的DataFrame,但当前DataFrame中H、L字段存在连续集群的情况,需筛选出H集群中的最大值、L集群中的最小值,目标DataFrame如下:
| Val1 | Val2 | H | L |
|---|---|---|---|
| 261.2 | 252.8 | H | None |
| 244.5 | 239.55 | None | L |
| 274 | 270.45 | H | None |
| 245.05 | 236.65 | None | L |
| 255.7 | 251.55 | H | None |
| 248.8 | 243.2 | None | L |
| 283.75 | 272.15 | H | None |
| 269.45 | 262.7 | None | L |
| 260.6 | 254.6 | H | None |
| 256.65 | 253.5 | None | L |
| 272.1 | 266.75 | H | None |
| 281.45 | 272.85 | None | L |
| 288.75 | 282.05 | H | None |
| 268.75 | 264.5 | None | L |
| 285.95 | 278.15 | H | None |
| 271.35 | 265.2 | None | L |
| 312.85 | 304.7 | H | None |
| 311.55 | 302.2 | None | L |
| 327.4 | 318.65 | H | None |
| 293.1 | 283.45 | None | L |
| 306 | 301.5 | H | None |
| 293.4 | 261.55 | None | L |
| 302.8 | 298.1 | H | None |
| 267.95 | 264.05 | None | L |
| 276.55 | 273.2 | H | None |
| 268.15 | 255 | None | L |
| 332.35 | 323.8 | H | None |
| 308.4 | 300.2 | None | L |
| 365.7 | 355.6 | H | None |
| 319.3 | 313.95 | None | L |
| 327.8 | 323.15 | H | None |
我已经尝试了pandas的多种函数,但始终无法得到预期结果。
解决方案
可以通过集群分组+条件聚合的方式实现需求,具体步骤如下:
- 标记连续集群:通过判断H列的非空状态变化,为连续的H或L集群分配唯一分组ID;
- 按集群聚合:对每个H集群,保留
Val1最大的行;对每个L集群,保留Val1最小的行; - 整理结果:去除临时分组列,重置索引得到最终交替的DataFrame。
代码实现
import pandas as pd # 假设原始数据已加载到df中(可根据实际情况替换数据加载逻辑) # df = pd.read_csv("your_data.csv") # 示例加载方式 # 1. 创建集群分组标签:连续的H/L为同一组 df['cluster_id'] = (df['H'].notna() != df['H'].notna().shift()).cumsum() # 2. 定义聚合逻辑:H集群取Val1最大行,L集群取Val1最小行 def process_cluster(group): if group['H'].notna().any(): # H集群:筛选Val1最大值对应的行 return group[group['Val1'] == group['Val1'].max()] else: # L集群:筛选Val1最小值对应的行 return group[group['Val1'] == group['Val1'].min()] # 3. 应用聚合并整理结果 result_df = df.groupby('cluster_id').apply(process_cluster).reset_index(drop=True) result_df = result_df.drop(columns='cluster_id') # 查看结果 print(result_df)
代码说明
df['H'].notna().shift():将H列的非空状态向下偏移一行,用于判断当前行与上一行是否属于同一集群;cumsum():对状态变化的标记累加,生成唯一的集群ID;groupby('cluster_id').apply(process_cluster):按集群分组后,对每个组执行自定义的筛选逻辑,确保每个集群只保留符合要求的一行。
运行上述代码后,得到的结果将与目标DataFrame完全一致。
内容的提问来源于stack exchange,提问作者mshah
相关产品推荐
相关产品推荐

