You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Pandas重塑/堆叠两列数据?

Pandas 重塑周度销售数据:宽表转长表 + 重复列名处理

嘿,我来帮你搞定这个Pandas数据重塑的问题,还有你提到的重复列名疑问~

首先,先明确你的核心需求:把宽表结构(每个产品一行,多列对应不同周的销售和单位)转换成长表结构(每个产品每周一行,对应该周的销售与单位)。下面分步骤给你解决方法:

一、先处理重复列名的问题

你提到用read_csv读取时,重复列名被自动命名为.1,这个是Pandas的默认行为,本身没有问题——它只是用来区分重复列名,避免列名冲突。但为了后续数据处理更清晰,建议手动把这些列名改成有意义的名称(比如给销售列加_Sales后缀,单位列加_Units后缀)。

处理方式两种:

  1. 读取CSV时直接指定列名(如果你知道原始列的含义):
import pandas as pd

# 自定义列名,明确区分销售和单位
col_names = [
    'Product', 'Desc1', 'Desc2', 'Desc3',
    'Week1_Sales', 'Week2_Sales', 'Week3_Sales',
    'Week1_Units', 'Week2_Units', 'Week3_Units'
]
# 读取CSV,指定列名并把Product设为索引
df = pd.read_csv('your_data.csv', names=col_names, header=0, index_col='Product')
  1. 读取后重命名列:
    如果已经读取了带.1后缀的数据,可以批量重命名:
# 假设原始列名是:Desc1, Desc2, Desc3, Week1, Week2, Week3, Week1.1, Week2.1, Week3.1
new_cols = ['Desc1', 'Desc2', 'Desc3']
# 处理销售列
new_cols += [f'{col}_Sales' for col in df.columns[3:6]]
# 处理单位列(把.1替换成_Units)
new_cols += [col.replace('.1', '_Units') for col in df.columns[6:]]
# 赋值新列名
df.columns = new_cols

二、核心:宽表转长表(实现你期望的结果)

这里用Pandas的wide_to_long函数最方便,它专门针对这种「前缀+编号」的列名结构做重塑:

# 先把索引(Product)转回普通列,方便后续处理
df_reset = df.reset_index()

# 使用wide_to_long转成长表
result = pd.wide_to_long(
    df_reset,
    stubnames=['Week_Sales', 'Week_Units'],  # 列名的前缀部分
    i=['Product', 'Desc1', 'Desc2', 'Desc3'],  # 保持不变的列(行标识)
    j='Week',  # 提取出的周编号,会变成新列
    sep='_',  # 前缀和编号之间的分隔符
    suffix='\\d+'  # 匹配编号的正则(这里是数字)
)

# 重置索引,并重命名列成你想要的格式
final_result = result.reset_index().rename(columns={
    'Week_Sales': 'Sales (By Week)',
    'Week_Units': 'Units (By Week)'
})

运行后,final_result就完全符合你期望的结构:每个产品每周对应一行,包含描述列、当周销售和单位数据。

关于你尝试的多级索引方法

你之前的多级索引构建有小问题——iterables应该是两个层级的列表,而不是把所有列混在一起。如果想用多级索引实现,也可以这样做:

# 给原始列构建多级索引(区分Sales和Units层级)
multi_cols = pd.MultiIndex.from_tuples([
    ('Desc', 'Desc1'), ('Desc', 'Desc2'), ('Desc', 'Desc3'),
    ('Sales', 'Week1'), ('Sales', 'Week2'), ('Sales', 'Week3'),
    ('Units', 'Week1'), ('Units', 'Week2'), ('Units', 'Week3')
])
df.columns = multi_cols

# 把Week层级从列转成行
result = df.stack(level=1).reset_index().rename(columns={'level_1': 'Week'})

但相比之下,wide_to_long更贴合你的数据结构,代码也更简洁。

内容的提问来源于stack exchange,提问作者Julian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:37:29