在Pandas中对相同值列分组且不聚合不同值列的实现方法
原始数据集
| A | B | Intensity | Area |
|---|---|---|---|
| 3 | 4 | 20.2 | 55 |
| 3 | 4 | 20.7 | 23 |
| 3 | 4 | 30.2 | 17 |
| 3 | 4 | 51.8 | 80 |
| 5 | 6 | 79.6 | 46 |
| 5 | 6 | 11.9 | 77 |
| 5 | 7 | 56.7 | 19 |
| 5 | 7 | 23.4 | 23 |
期望输出格式
| A,B | |||||
|---|---|---|---|---|---|
| Intensity | 3,4 | 20.2 | 20.7 | 30.2 | 51.8 |
| 5,6 | 79.6 | 11.9 | NaN | NaN | |
| 5,7 | 56.7 | 23.4 | NaN | NaN | |
| Area | 3,4 | 55 | 23 | 17 | 80 |
| 5,6 | 46 | 77 | NaN | NaN | |
| 5,7 | 19 | 23 | NaN | NaN |
解决方案代码
import pandas as pd # 读取实际数据(此处用示例数据代替) df = pd.DataFrame({ 'A': [3,3,3,3,5,5,5,5], 'B': [4,4,4,4,6,6,7,7], 'Intensity': [20.2,20.7,30.2,51.8,79.6,11.9,56.7,23.4], 'Area': [55,23,17,80,46,77,19,23] }) # 1. 为每组添加组内序号,用于将纵向值转为横向列 df['group_seq'] = df.groupby(['A','B']).cumcount() # 2. 将Intensity和Area分别转成宽表格式 intensity_wide = df.pivot(index=['A','B'], columns='group_seq', values='Intensity').reset_index() area_wide = df.pivot(index=['A','B'], columns='group_seq', values='Area').reset_index() # 3. 合并A、B列为"A,B"格式字符串 intensity_wide['A,B'] = intensity_wide.apply(lambda row: f"{row['A']},{row['B']}", axis=1) area_wide['A,B'] = area_wide.apply(lambda row: f"{row['A']},{row['B']}", axis=1) # 4. 添加指标标识列 intensity_wide.insert(0, 'Metric', 'Intensity') area_wide.insert(0, 'Metric', 'Area') # 5. 合并两个宽表并调整格式 result = pd.concat([intensity_wide, area_wide], ignore_index=True) result = result.drop(columns=['A','B']).set_index('Metric') # 6. 重命名列,匹配目标表头格式 result.columns = ['A,B'] + ['' for _ in result.columns[1:]] # 7. 清除重复的指标标识 result['Metric'] = result.index result.loc[result.duplicated(subset='Metric', keep='first'), 'Metric'] = '' result = result.set_index('Metric') print(result)
代码说明
- 用
cumcount()给每组内的记录生成序号,是将纵向原始值转为横向列的关键。 pivot()方法实现长表转宽表,把每组的多个原始值横向展开。- 合并A、B列成指定格式字符串,添加指标标识列后,通过
concat()合并结果,最后调整索引和列名匹配目标输出。
内容的提问来源于stack exchange,提问作者Teddy
相关产品推荐
相关产品推荐

