基于DataFrame中group与y值变化生成subgroup和count列
问题描述
已有如下排序完成的DataFrame:
d = {'x': [1479903, 1479879, 1479926, 1479736, 1479760, 1479784, 1479808, 1479831, 1480331, 1480355, 1480949, 1480973, 1480997, 1481021, 1481877, 1481901, 1481924, 1481948, 1481996, 1482020], 'y': [7195293, 7195293, 7195293, 7194829, 7194829, 7194829, 7194829, 7194829, 7194829, 7194829, 7194384, 7194384, 7194384, 7194384, 7194384, 7194384, 7194384, 7194384, 7193920, 7193920], 'group':[1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3]} df = pd.DataFrame(data=d) df = df.sort_values(by = ['group', 'y','x'], ascending = [True, False, True])
需要新增两列:
- subgroup:初始值为1,仅当
y值变化时递增;group值变化时重置为1 - count:同一
subgroup内从1开始递增,subgroup变化时重置为1
期望输出
| group | subgroup | count | x | y |
|---|---|---|---|---|
| 1 | 1 | 1 | 1479879 | 7195293 |
| 1 | 1 | 2 | 1479903 | 7195293 |
| 1 | 1 | 3 | 1479926 | 7195293 |
| 1 | 2 | 1 | 1479736 | 7194829 |
| 1 | 2 | 2 | 1479760 | 7194829 |
| 1 | 2 | 3 | 1479784 | 7194829 |
| 1 | 2 | 4 | 1479808 | 7194829 |
| 1 | 2 | 5 | 1479831 | 7194829 |
| 2 | 1 | 1 | 1480331 | 7194829 |
| 2 | 1 | 2 | 1480355 | 7194829 |
| 2 | 2 | 1 | 1480949 | 7194384 |
| 2 | 2 | 2 | 1480973 | 7194384 |
| 2 | 2 | 3 | 1480997 | 7194384 |
| 2 | 2 | 4 | 1481021 | 7194384 |
| 3 | 1 | 1 | 1481877 | 7194384 |
| 3 | 1 | 2 | 1481901 | 7194384 |
| 3 | 1 | 3 | 1481924 | 7194384 |
| 3 | 1 | 4 | 1481948 | 7194384 |
| 3 | 2 | 1 | 1481996 | 7193920 |
| 3 | 2 | 2 | 1482020 | 7193920 |
解决方案
使用Pandas的分组与累加函数实现需求:
# 标记每个group内y值的变化点 df['y_change'] = df.groupby('group')['y'].shift() != df['y'] # 填充第一行的空值(默认视为y值变化起点) df['y_change'] = df['y_change'].fillna(True) # 计算subgroup:按group分组后累加变化标记 df['subgroup'] = df.groupby('group')['y_change'].cumsum().astype(int) # 计算count:按group+subgroup分组后从1开始计数 df['count'] = df.groupby(['group', 'subgroup']).cumcount() + 1 # 删除中间辅助列(可选操作) df = df.drop('y_change', axis=1) # 调整列顺序匹配期望输出 df = df[['group', 'subgroup', 'count', 'x', 'y']]
逻辑说明
- 标记y值变化:通过
shift()获取每组内上一行的y值,与当前行比较得到变化标记,第一行默认作为变化起点 - 生成subgroup:对每个group内的变化标记做累加,每次y值变化时数值加1,group切换时重新开始计数
- 生成count:按
group和subgroup分组,用cumcount()+1实现组内从1开始的递增计数
内容的提问来源于stack exchange,提问作者matteo112
相关产品推荐
相关产品推荐

