如何将含重复分组列的Pandas DataFrame重塑为长格式?
Pandas 拆分重复列并重组DataFrame解决方案
问题概述
导入的大型表格中,前18列为每行必备的必要列,后续包含7组列名完全重复的9列(每组对应不同的行数据)。需要将这些重复列拆分后,分别与必要列组合成统一结构的新DataFrame,但手动使用drop、iloc等方法时出现报错:ValueError: operands could not be broadcast together with shapes (9,) (44,)。
示例数据
原DataFrame
| ID | Name | Category | Year | Choice | Price | Year | Choice | Price | Year | Choice | Price |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Test | AM | 2022 | A | 10 | 2022 | B | 11 | 2023 | B | 11.5 |
期望转换结果
| ID | Name | Category | Year | Choice | Price |
|---|---|---|---|---|---|
| 1 | Test | AM | 2022 | A | 10 |
| 1 | Test | AM | 2022 | B | 11 |
| 1 | Test | AM | 2023 | B | 11.5 |
错误原因
手动通过列索引删除多余列的方式,容易因列数计算错误导致保留的重复列与必要列的行数/列数不匹配,进而触发形状广播错误。更高效可靠的方式是使用Pandas专门处理宽表转长表的工具函数。
解决方案代码
针对示例数据的实现
import pandas as pd # 构造示例数据 data = { 'ID': [1], 'Name': ['Test'], 'Category': ['AM'], 'Year': [2022], 'Choice': ['A'], 'Price': [10], 'Year': [2022], 'Choice': ['B'], 'Price': [11], 'Year': [2023], 'Choice': ['B'], 'Price': [11.5] } df = pd.DataFrame(data) # 自动处理重复列名,添加后缀区分 df.columns = pd.io.parsers.base_parser.ParserBase({'usecols': None})._maybe_dedup_names(df.columns) # 提取必要列 id_cols = ['ID', 'Name', 'Category'] # 定义需要拆分的重复列名 stubnames = ['Year', 'Choice', 'Price'] # 转换为长表格式 result = pd.wide_to_long(df, stubnames=stubnames, i=id_cols, j='group', sep='.', suffix='\\d+').reset_index() # 移除临时生成的group列(不需要可删除此步) result = result.drop('group', axis=1) print(result)
针对你的实际场景(前18列+7组9重复列)
import pandas as pd # 假设df是你导入的原始DataFrame # 1. 自动处理重复列名,避免列名冲突 df.columns = pd.io.parsers.base_parser.ParserBase({'usecols': None})._maybe_dedup_names(df.columns) # 2. 提取前18个必要列 id_cols = df.columns[:18].tolist() # 3. 定义9个重复的列名(替换成你实际的列名,比如['Year', 'Choice', 'Price', ...]) stubnames = ['列名1', '列名2', ..., '列名9'] # 4. 执行宽表转长表转换 result = pd.wide_to_long(df, stubnames=stubnames, i=id_cols, j='group', sep='.', suffix='\\d+').reset_index() # 5. 移除临时group列并重置索引 result = result.drop('group', axis=1).reset_index(drop=True) # 查看最终结果 print(result)
代码说明
- 重复列名处理:通过
_maybe_dedup_names自动为重复列名添加后缀(如Year→Year.1),避免列名冲突。 - wide_to_long函数:专门用于将宽表转换为长表,通过
i指定必要列(标识行),stubnames指定需要拆分的重复列前缀,自动完成拆分与合并。 - 避免手动索引错误:无需手动计算列索引位置,彻底解决形状不匹配的报错问题。
内容的提问来源于stack exchange,提问作者Jon Garnett-Smith
相关产品推荐
相关产品推荐

