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

Pandas展开多列列表遇阻,求适配不等长列表的解决方案

问题描述

我已经尝试过站内所有相关方法但均无效,请不要标记为重复问题,当前问题存在特殊性。

我有如下格式的JSON数据(包含500条重复结构的Id数据,还有其他非列表类型列):

[
    {
        "Id": 1,
        "Design": ["09", "10", "13"],
        "Research": ["Eng", "Math"]
    }
]

我需要展开其中的列表列,最终输出为Excel文件,无论直接处理JSON还是用Pandas均可。

已尝试的方法及问题

  • 自定义函数方法:

    def lenx(x):
        return len(x) if isinstance(x,(list, tuple, np.ndarray, pd.Series)) else 1
    
    def cell_size_equalize2(row, cols='', fill_mode='internal', fill_value=''):
        jcols = [j for j,v in enumerate(row.index) if v in cols]
        if len(jcols)<1:
            jcols = range(len(row.index))
        Ls = [lenx(x) for x in row.values]
        if not Ls[:-1]==Ls[1:]:
            vals = [v if isinstance(v,list) else [v] for v in row.values]
            if fill_mode=='external':
                vals = [[e] + [fill_value]*(max(Ls)-1) if (not j in jcols) and (isinstance(row.values[j],list))
                        else e + [fill_value]*(max(Ls)-lenx(e))
                        for j,e in enumerate(vals)]
            elif fill_mode == 'internal':
                vals = [[e]+[e]*(max(Ls)-1) if (not j in jcols) and (isinstance(row.values[j],list))
                        else e+[e[-1]]*(max(Ls)-lenx(e)) 
                        for j,e in enumerate(vals)]
            else:
                vals = [e[0:min(Ls)] for e in vals]
            row = pd.Series(vals,index=row.index.tolist())
        return row
    

    运行后引发索引错误。

  • Pandas explode多列方法:

    df.explode(['B', 'C', 'D', 'E']).reset_index(drop=True)
    

    提示列必须长度相同。

  • 逐列展开后拼接方法:

    df1 = pd.concat([df[x].explode().to_frame()
                          .assign(g=lambda x: x.groupby(level=0).cumcount())
                          .set_index('g', append=True) 
                    for x in cols_to_explode], axis=1)
    

    生成大量冗余行,疑似因逐列展开导致内存错误。

期望输出格式

IdDesignResearch
109Eng
110Math
113

解决方案

方案一:Pandas 处理(推荐)

核心思路是对每个列表列单独展开并保留分组计数,再按分组和原始索引合并,最后填充空值并整理:

import pandas as pd

# 读取JSON数据(假设文件名为data.json)
df = pd.read_json('data.json')

# 指定需要展开的列表列
cols_to_explode = ['Design', 'Research']

# 为每个列表列生成带分组计数的DataFrame
exploded_dfs = []
for col in cols_to_explode:
    exploded = df[col].explode().reset_index()
    exploded['group'] = exploded.groupby('index').cumcount()
    exploded_dfs.append(exploded.pivot(index=['index', 'group'], columns='level_1', values=col).reset_index())

# 合并所有展开后的DataFrame
merged = exploded_dfs[0]
for df_exp in exploded_dfs[1:]:
    merged = pd.merge(merged, df_exp, on=['index', 'group'], how='outer')

# 合并原始DataFrame中的非列表列
final_df = pd.merge(df.drop(cols_to_explode, axis=1), merged, left_index=True, right_on='index').drop(['index', 'group'], axis=1)

# 重置索引并保存为Excel
final_df.reset_index(drop=True).to_excel('output.xlsx', index=False)

方案二:直接处理JSON生成结构化数据

如果Pandas内存压力大,可以直接遍历JSON数据生成目标格式的列表,再转成DataFrame:

import pandas as pd
import json

# 读取JSON数据
with open('data.json', 'r') as f:
    data = json.load(f)

# 指定需要展开的列表列
cols_to_explode = ['Design', 'Research']

# 生成目标结构的列表
output_data = []
for item in data:
    # 获取非列表字段
    non_list_fields = {k: v for k, v in item.items() if not isinstance(v, list)}
    # 找到最长的列表列长度
    max_len = max(len(v) for k, v in item.items() if isinstance(v, list))
    # 逐行生成数据
    for i in range(max_len):
        row = non_list_fields.copy()
        for col in cols_to_explode:
            row[col] = item[col][i] if i < len(item[col]) else None
        output_data.append(row)

# 转成DataFrame并保存
pd.DataFrame(output_data).to_excel('output.xlsx', index=False)

这两种方案都能处理列表列长度不一致的情况,不会生成冗余行,适配500条数据的规模。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:49:54