Pandas如何合并3列为1列且单独保留Amount列的对应值
层级列展开实现方案
需求说明
源数据为4列结构,列名分别为Subclass、Subclass2、Layer、Amount,其中前3列为从上到下的层级映射关系,需要将3个层级列按顺序合并为单列Col1,仅最末层级Layer对应的行保留原Amount值,上层级行的Amount置为NaN,最终输出仅含Col1、Amount两列的结果。
样例源数据:
| Subclass | Subclass2 | Layer | Amount |
|---|---|---|---|
| A | B | C | 5 |
| E | F | G | 100 |
目标输出:
| Col1 | Amount |
|---|---|
| A | NaN |
| B | NaN |
| C | 5 |
| E | NaN |
| F | NaN |
| G | 100 |
原有melt写法问题
之前执行的df.melt(id_vars = ['SubClass', 'SubClass2'], value_name = 'CQ')存在两个核心错误:
- 列名大小写不匹配:源列名为
Subclass,代码中写为SubClass - 参数逻辑错误:未明确指定要展开的3个层级列,也未配置
Amount列的保留规则,默认会将Amount也作为维度列做展开,最终列结构完全错乱。
实现代码
方法1:逐行构造(逻辑直观,顺序绝对匹配)
适合数据量不大的场景,不需要额外处理排序问题,严格按照Subclass→Subclass2→Layer的顺序生成结果:
import pandas as pd import numpy as np # 构造测试源数据 df = pd.DataFrame({ 'Subclass': ['A', 'E'], 'Subclass2': ['B', 'F'], 'Layer': ['C', 'G'], 'Amount': [5, 100] }) rows = [] for _, row in df.iterrows(): rows.append({'Col1': row['Subclass'], 'Amount': np.nan}) rows.append({'Col1': row['Subclass2'], 'Amount': np.nan}) rows.append({'Col1': row['Layer'], 'Amount': row['Amount']}) result = pd.DataFrame(rows)
方法2:修正melt逻辑(性能更优,适合大数据量)
通过正确传参给melt实现宽转长,再通过分类排序保证层级顺序,最后修正Amount值:
# 宽转长,保留Amount为标识列,展开三个层级列 melt_df = df.melt( id_vars=['Amount'], value_vars=['Subclass', 'Subclass2', 'Layer'], var_name='level_tag', value_name='Col1' ) # 指定层级顺序,排序保证行顺序符合要求 melt_df['level_tag'] = pd.Categorical( melt_df['level_tag'], categories=['Subclass', 'Subclass2', 'Layer'], ordered=True ) melt_df = melt_df.sort_values(by=['Amount', 'level_tag']).reset_index(drop=True) # 非Layer层级的Amount置为NaN melt_df.loc[melt_df['level_tag'] != 'Layer', 'Amount'] = np.nan # 提取需要的两列得到最终结果 result = melt_df[['Col1', 'Amount']]
NaN值替换
如果需要将结果中的NaN替换为0或者空值,直接调用fillna即可:
# 替换为0 result['Amount'] = result['Amount'].fillna(0) # 替换为空字符串 result['Amount'] = result['Amount'].fillna('')
内容的提问来源于stack exchange,提问作者user18233539
相关产品推荐
相关产品推荐

