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

针对命名不一致的大型数据集,如何使用melt或wide_to_long处理?

宽表转长表:解决内存溢出与pd.wide_to_long适配问题

我有一个大型数据集,手动分析难度极大。数据集的通用结构包含16个ItemType0相关列、16个ItemType1相关列、16个ItemType2相关列等,每一行记录单个时间步长下最多16个不同项目的多项属性,以及该时间步长自身的属性。

原数据集示例

TimeItemType0[0].propertyItemType0[1].propertyProperty
1102
2012
3332

期望输出数据集

TimeItemType0.propertyProperty
112
202
332
102
212
332

数据集复现代码

import pandas as pd

wide_df = pd.DataFrame({
    "Time": [1,2,3],
    "ItemType0[0].property": [1,0,3],
    "ItemType0[1].property": [0,1,3],
    "Property": [2,2,2]})

已尝试的方法

  • 使用melt全量转换:
    ids = [col for col in wide_df.columns if "[" not in col]
    inter_df = pd.melt(wide_df, id_vars=ids, var_name="Source")
    
    触发内存错误:MemoryError: Unable to allocate 28.3 GiB for an array with shape (15,506831712) and data type uint32
  • 无法直接使用pd.wide_to_long,因为列名格式不符合函数要求。

解决方案

方案1:分批次处理避免内存溢出

针对超大型数据集,全量melt会瞬间占满内存,改用分块读取+分块转换的方式:

import pandas as pd

chunk_size = 100000  # 根据内存情况调整块大小
ids = [col for col in wide_df.columns if "[" not in col]
result = []

# 如果数据集来自CSV文件,用read_csv分块读取;如果是DataFrame,用iloc切分
for start in range(0, len(wide_df), chunk_size):
    chunk = wide_df.iloc[start:start+chunk_size]
    melted_chunk = pd.melt(chunk, id_vars=ids, var_name="Source", value_name="ItemType0.property")
    # 清理无用列,只保留需要的字段
    melted_chunk = melted_chunk.drop(columns=["Source"])
    result.append(melted_chunk)

final_df = pd.concat(result, ignore_index=True)

这种方式把大数据集拆成小块处理,每次只加载部分数据到内存,从根本上避免内存溢出。

方案2:适配列名后使用pd.wide_to_long

pd.wide_to_long比melt更高效,但需要列名符合前缀_索引的格式。我们可以先重命名列,把原列名中的[Y]转换成后缀:

import pandas as pd

# 批量重命名列:ItemType0[0].property → ItemType0.property_0
col_mapping = {}
for col in wide_df.columns:
    if "[" in col:
        base_part, idx_part = col.split("[")
        idx = idx_part.split("]")[0]
        col_mapping[col] = f"{base_part}_{idx}"

renamed_df = wide_df.rename(columns=col_mapping)

# 调用wide_to_long转换
long_df = pd.wide_to_long(
    renamed_df,
    stubnames=["ItemType0.property"],  # 要转换的列前缀
    i=["Time", "Property"],  # 保留的标识符列
    j="item_index",  # 索引列的名称(转换后可删除)
    sep="_",
    suffix=r"\d+"  # 匹配索引数字
).reset_index().drop(columns=["item_index"])

如果有多个ItemType(比如ItemType1、ItemType2),可以循环处理每个类型的列,最后合并结果即可。这个方法内存占用远低于melt,适合大型数据集。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:52:12