You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame组间Placement序列识别与跨行计算实现方案

问题描述

现有一个Pandas DataFrame,数据按Group分组,每组是Placement值相同的连续行;Placement包含low、lowmed、highmed、high四个层级,且连续组的Placement值不会重复。需求如下:

  • 识别组间Placement变化跨度≥2且无反向中断的情况
  • 对符合条件的情况,计算前一组最后一行与当前组第一行的Value差值
  • 将当前组第一行存入新DataFrame,并新增Diff(差值)和Measured_From(前一组最后一行的Order值)列

输入示例

import pandas as pd

df = pd.DataFrame({
    'Placement': ['high', 'high', 'high', 'highmed', 'highmed', 'lowmed', 'low', 'low', 'lowmed', 'lowmed', 'highmed', 'lowmed', 'high', 'highmed', 'low'],
    'Value': [10, 8, 9, 7, 6, 4, 1, 2, 4, 5, 7, 5, 8, 5, 1],
    'Order': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
    'Group': [1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10]
})

输出示例

Placement  Value  Order  Group  Diff  Measured_From
5   lowmed      4      6      3     5          2
6   low         1      7      4     5          4
6   low         1      7      4     8          2
10  highmed     7      11     6     5          7
12  high        8      13     8     3          11
14  low         1      15     10    4          13
14  low         1      15     10    7          12

用户原有思路:将Placement转为数值,检查当前组的前3个组:先检查组N-1,若与组N的Placement差值≥2则计算并记录;再检查组N-2,若差值小于N-1或方向反向则停止。但原代码因新增Placement值和多行组不再适用,寻求高效实现方案。

解决方案

步骤1:映射Placement到数值

给四个层级赋值,方便计算跨度:

placement_map = {'low': 0, 'lowmed': 1, 'highmed': 2, 'high': 3}

步骤2:提取组的关键信息

聚合每个组的核心数据,减少后续计算量:

# 获取每个组的首行数据
group_first = df.groupby('Group').first().reset_index()
# 获取每个组末行的Order和Value
group_last = df.groupby('Group').agg({'Order': 'last', 'Value': 'last'}).reset_index()
# 合并组的首末信息,添加Placement对应的数值
group_info = pd.merge(group_first, group_last, on='Group', suffixes=('', '_last'))
group_info['Placement_num'] = group_info['Placement'].map(placement_map)

步骤3:遍历组,查找符合条件的前置组

对每个组向前遍历前置组,判断是否满足跨度≥2且无反向中断(反向中断指当前组与前置组的变化方向,和紧邻前置组的变化方向相反),一旦出现反向或跨度不足则停止查找:

result_rows = []

for i in range(1, len(group_info)):
    current_group = group_info.iloc[i]
    current_pnum = current_group['Placement_num']
    # 提取当前组首行的基础数据
    base_row = current_group[['Placement', 'Value', 'Order', 'Group']].to_dict()
    
    prev_dir = None  # 记录上一个变化方向
    for j in range(i-1, -1, -1):
        prev_group = group_info.iloc[j]
        prev_pnum = prev_group['Placement_num']
        span = abs(current_pnum - prev_pnum)
        curr_dir = current_pnum - prev_pnum
        
        # 出现反向中断则停止向前查找
        if prev_dir is not None and curr_dir * prev_dir < 0:
            break
        
        # 跨度≥2则记录结果
        if span >= 2:
            diff = abs(current_group['Value'] - prev_group['Value_last'])
            row = base_row.copy()
            row['Diff'] = diff
            row['Measured_From'] = prev_group['Order_last']
            result_rows.append(row)
        
        prev_dir = curr_dir

# 转换为DataFrame并按Order排序
result_df = pd.DataFrame(result_rows).sort_values('Order').reset_index(drop=True)

效率说明

  • 先通过聚合将数据压缩到组级别,避免逐行处理的冗余计算
  • 前置组遍历遇到反向中断立即停止,减少不必要的循环

内容的提问来源于stack exchange,提问作者Jordan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 04:16:33