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

如何在Pandas中仅堆叠DataFrame指定列子集实现行复制?

处理重复列组的DataFrame堆叠转换问题

问题背景

从XML文件生成的数组转换为DataFrame后,前n列为通用信息(每行所有产品共享该内容),后24列包含8组重复的列名组合["Product", "Name", "Price"]。需要将这些重复列组按每3列一组堆叠,得到以下两种格式之一:

  • 格式1:通用列仅第一行保留,后续产品行通用列留空
  • 格式2:每一行产品都复制对应的通用列信息

初始数据结构

LocationDescriptionStatus.....ProductNamePriceProductNamePrice...
1"Foo"11244.21228.8
2"Bar"11228.9NaNNaN

目标格式示例

格式1

LocationDescriptionStatus.....ProductNamePrice
1"Foo"11244.2
1228.8
2"Bar"11228.9
NaNNaN

格式2

LocationDescriptionStatus.....ProductNamePrice
1"Foo"11244.2
1"Foo"11228.8
2"Bar"11228.9
2"Bar"1NaNNaN

已尝试的方法

步骤1:重命名重复列名

cols=pd.Series(result_list_xml_t[0])
for dup in cols[cols.duplicated()].unique(): 
    cols[cols[cols == dup].index.values.tolist()] = [dup + '.' + str(i) if i != 0 else dup for i in range(sum(cols == dup))]

步骤2:创建多级索引列

columns_xml = pd.MultiIndex.from_arrays([xml_groups,cols])

生成的DataFrame结构:

baseprod1prod2...
LocationDescriptionStatus.....
11"Foo"1
22"Bar"1

尝试过df.stack(future_stack=True,level=0)及melt()+set_index()组合,未得到预期结果。

解决方案

方法1:使用pd.wide_to_long(推荐,简洁高效)

该方法专门处理重复列组的宽表转长表需求,无需复杂的手动列处理:

# 替换为实际的通用列数量
n_base_cols = 3
base_cols = df.columns[:n_base_cols].tolist()
product_cols = df.columns[n_base_cols:]

# 给每组3列添加组号后缀(如_1、_2..._8)
new_product_cols = []
for i in range(0, len(product_cols), 3):
    group = product_cols[i:i+3]
    new_product_cols.extend([f"{col}_{i//3 + 1}" for col in group])

# 重命名DataFrame列
df.columns = base_cols + new_product_cols

# 转换为长表(格式2)
result_format2 = pd.wide_to_long(
    df,
    stubnames=["Product", "Name", "Price"],
    i=base_cols,
    j="product_group",
    sep="_",
    suffix=r"\d+"
).reset_index(drop=False)

# 转换为格式1(通用列重复行留空)
result_format1 = result_format2.copy()
result_format1[base_cols] = result_format1[base_cols].mask(
    result_format1.duplicated(subset=base_cols, keep="first")
)

方法2:基于多级索引的stack实现

如果已经创建了多级索引列,可通过以下步骤转换:

# 将通用列设为索引
base_cols = [col for col in df.columns if col[0] == "base"]
df_indexed = df.set_index(base_cols)

# 堆叠所有prod开头的列组
stacked = df_indexed.stack(level=0).reset_index()

# 清理列名
stacked.columns = [col if col != "level_0" else "product_group" for col in stacked.columns]

# 格式2直接使用stacked,格式1处理通用列重复值
result_format1 = stacked.copy()
result_format1[base_cols] = result_format1[base_cols].mask(
    result_format1.duplicated(subset=base_cols, keep="first")
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:46:00