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

如何基于ID及Bxx数值增减变化对DataFrame数据分组?

实现Pandas DataFrame按A前缀+B数值升降转向分组

给定含ID列的DataFrame,ID格式为Axx-Bxx,需新增GROUP列,分组规则:

  • 先按Axx前缀分组
  • 每个Axx组内,按Bxx数值的升降转向(趋势变化点)划分小组

示例输入

import pandas as pd
df = pd.DataFrame({
    'ID': ['A01-B01', 'A01-B03', 'A01-B02', 'A01-B04', 'A02-B05', 'A02-B04', 'A02-B03']
})

期望输出

IDGROUP
A01-B01A01-1
A01-B03A01-1
A01-B02A01-2
A01-B04A01-3
A02-B05A02-1
A02-B04A02-1
A02-B03A02-1

实现步骤

1. 提取分组所需字段

拆分ID得到Axx前缀和Bxx的数值:

# 拆分A前缀和B部分
df[['A_group', 'B_part']] = df['ID'].str.split('-', expand=True)
# 提取B部分的数值并转为整数
df['B_num'] = df['B_part'].str.extract(r'(\d+)').astype(int)

2. 计算每个A组内的趋势转向点

通过计算B_num的差值符号,判断趋势变化(上升/下降),然后标记转向点并累加得到组内序号:

import numpy as np

# 计算每个A组内B_num的差值,得到变化量
df['diff'] = df.groupby('A_group')['B_num'].diff()
# 将差值转为符号:1=上升,-1=下降,0=不变
df['trend_sign'] = df['diff'].apply(lambda x: np.sign(x) if pd.notna(x) else 0)
# 标记趋势转向点:当前趋势符号与前一行不同则为1,否则为0
df['trend_change'] = df.groupby('A_group')['trend_sign'].apply(lambda x: (x != x.shift()).astype(int)).reset_index(level=0, drop=True)
# 累加转向点得到组内分组序号
df['group_in_A'] = df.groupby('A_group')['trend_change'].cumsum()

3. 生成最终GROUP列

将A_group和组内序号拼接:

df['GROUP'] = df['A_group'] + '-' + df['group_in_A'].astype(str)
# 可选:删除中间辅助列
df = df.drop(['A_group', 'B_part', 'B_num', 'diff', 'trend_sign', 'trend_change', 'group_in_A'], axis=1)

完整代码

import pandas as pd
import numpy as np

# 示例输入
df = pd.DataFrame({
    'ID': ['A01-B01', 'A01-B03', 'A01-B02', 'A01-B04', 'A02-B05', 'A02-B04', 'A02-B03']
})

# 提取字段
df[['A_group', 'B_part']] = df['ID'].str.split('-', expand=True)
df['B_num'] = df['B_part'].str.extract(r'(\d+)').astype(int)

# 计算趋势转向与组内序号
df['diff'] = df.groupby('A_group')['B_num'].diff()
df['trend_sign'] = df['diff'].apply(lambda x: np.sign(x) if pd.notna(x) else 0)
df['trend_change'] = df.groupby('A_group')['trend_sign'].apply(lambda x: (x != x.shift()).astype(int)).reset_index(level=0, drop=True)
df['group_in_A'] = df.groupby('A_group')['trend_change'].cumsum()

# 生成GROUP列并清理
df['GROUP'] = df['A_group'] + '-' + df['group_in_A'].astype(str)
df = df.drop(['A_group', 'B_part', 'B_num', 'diff', 'trend_sign', 'trend_change', 'group_in_A'], axis=1)

print(df)

运行后输出与期望完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:57:27