如何对DataFrame分组执行melt操作?现有代码生成冗余行求解决
问题分析与解决方法
问题背景
原始数据来自Excel,无法直接分享,构造的模拟DataFrame代码如下:
df = pd.DataFrame({0: ['id', 'id1', 'id', 'id2', 'id1', 'id', 'id3', 'id2'], 1: ['col1', '1', 'col1', '4', '6', None, None, None], 2: ['col2', '2', None, None, None, 'col2', None, '8'], 3: ['col3', '3', 'col3', '5', '7', None, None, None]})
输出的原始DataFrame:
0 1 2 3 0 id col1 col2 col3 1 id1 1 2 3 2 id col1 NaN col3 3 id2 4 NaN 5 4 id1 6 NaN 7 5 id NaN col2 NaN 6 id3 NaN NaN NaN 7 id2 NaN 8 NaN
期望将数据整理为如下格式:
id number variable value id1 1 col1 1 id1 1 col2 2 id1 1 col3 3 id2 2 col1 4 id2 2 col2 id2 2 col3 5 id1 2 col1 6 id1 2 col2 id1 2 col3 7 id3 3 col1 id3 3 col2 id3 3 col3 id2 3 col1 id2 3 col2 8 id2 3 col3
现有代码的问题
你编写的代码产生多余行的核心原因是:
- 分组后每个子DataFrame包含了开头的
id行(变量名定义行)和数据行,直接对整个子DF执行melt会把变量名行也转换成数据行,比如输出头部里的id行条目就是多余的 - 未正确设置
melt的var_name和value_name参数,导致列名不符合期望格式
解决方法
正确的处理逻辑是区分每个分组里的变量名行和数据行,步骤如下:
- 按
id行分组后,提取每个分组的第一行作为该组的列名 - 取分组中剩余的行作为有效数据行,重置索引并应用新列名
- 对数据行执行
melt,指定id_vars为id列,同时设置变量和值的列名 - 添加
number编号,合并所有分组结果并调整列顺序
完整代码:
import pandas as pd # 模拟DataFrame df = pd.DataFrame({0: ['id', 'id1', 'id', 'id2', 'id1', 'id', 'id3', 'id2'], 1: ['col1', '1', 'col1', '4', '6', None, None, None], 2: ['col2', '2', None, None, None, 'col2', None, '8'], 3: ['col3', '3', 'col3', '5', '7', None, None, None]}) # 按id行进行分组 groups = df.groupby(df[0].eq('id').cumsum()) final_dfs = [] number = 1 for _, group in groups: # 提取分组第一行作为列名 var_names = group.iloc[0].values # 提取分组中除第一行外的数据行 data = group.iloc[1:].reset_index(drop=True) # 为数据行设置列名 data.columns = var_names # 执行melt转换,指定id列、变量列和值列的名称 melted_data = data.melt(id_vars='id', var_name='variable', value_name='value') # 添加number编号 melted_data['number'] = number final_dfs.append(melted_data) number += 1 # 合并所有分组结果 result = pd.concat(final_dfs, ignore_index=True) # 调整列顺序以匹配期望输出 result = result[['id', 'number', 'variable', 'value']] # 将NaN替换为空字符串(可选,根据需求调整) result['value'] = result['value'].fillna('') print(result)
执行后将得到与期望一致的输出。
内容的提问来源于stack exchange,提问作者VERBOSE
相关产品推荐
相关产品推荐

