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

如何将Pandas DataFrame指定行的列表型单元格拆分为多行并匹配列值

问题

现有如下结构的Pandas DataFrame:

labelpredgt
label1val1val11
label2['str1', 'str2']['str1', 'str3', 'str4']
label3foobox

需要将label2行中pred和gt列的列表型数据拆分为多行,列表长度不一致时用None补全,期望结果如下:

labelpredgt
label1val1val11
label2'str1''str1'
label2'str2''str3'
label2None'str4'
label3foobox

尝试使用explode()方法实现,但得到的新DataFrame全为NaN值,且拆分后的行未匹配到正确label,代码如下:

df_filtered = output_df[output_df['label'] == 'label2']

# explode the list column into multiple rows while keeping other columns
df_exploded = pd.concat([
    df_filtered.drop(['pred', 'gt'], axis=1),
    df_filtered['pred'].explode().reset_index(drop=True),
    df_filtered['gt'].explode().reset_index(drop=True)
], axis=1)

# add prefix to the existing column name (label) to differentiate each new row
df_exploded = df_exploded.add_prefix('new_')

# rename the columns to remove the prefix from the original column
df_exploded = df_exploded.rename(columns={'new_pred': 'pred', 'new_gt': 'gt'})

# combine the exploded dataframe with the original dataframe, dropping the original list column
df_combined = pd.concat([output_df.drop(['pred', 'gt'], axis=1), df_exploded], axis=1)

解决方案

问题分析

你原来的代码有两个核心问题:

  1. reset_index(drop=True)破坏了原数据的索引关联,导致label和拆分后的pred/gt无法正确对齐;
  2. 最后合并时直接拼接原DataFrame和拆分后的DataFrame,没有替换原label2行,导致结构混乱出现NaN。

正确实现方法

可以通过「分离目标行→对齐拆分→合并结果」的步骤实现需求:

代码实现(兼容所有Pandas版本)

import pandas as pd

# 构造示例数据(已有output_df可跳过此步)
output_df = pd.DataFrame({
    'label': ['label1', 'label2', 'label3'],
    'pred': ['val1', ['str1', 'str2'], 'foo'],
    'gt': ['val11', ['str1', 'str3', 'str4'], 'box']
})

# 1. 拆分需要处理和不需要处理的行
non_target_df = output_df[output_df['label'] != 'label2'].copy()
target_df = output_df[output_df['label'] == 'label2'].copy()

# 2. 对目标行的pred/gt做对齐拆分:统一长度,不足补None
def split_aligned(row):
    pred_list = row['pred']
    gt_list = row['gt']
    max_length = max(len(pred_list), len(gt_list))
    # 补全短列表到最长长度
    padded_pred = pred_list + [None] * (max_length - len(pred_list))
    padded_gt = gt_list + [None] * (max_length - len(gt_list))
    return pd.DataFrame({
        'label': [row['label']] * max_length,
        'pred': padded_pred,
        'gt': padded_gt
    })

# 应用拆分函数到目标行
split_result = target_df.apply(split_aligned, axis=1).explode('_0')['_0'].apply(pd.Series)

# 3. 合并所有行
final_df = pd.concat([non_target_df, split_result], ignore_index=True)

# 可选:给字符串添加引号,匹配示例格式
final_df['pred'] = final_df['pred'].apply(lambda x: f"'{x}'" if pd.notna(x) else x)
final_df['gt'] = final_df['gt'].apply(lambda x: f"'{x}'" if pd.notna(x) else x)

print(final_df)

简化实现(Pandas 2.0+)

如果使用Pandas 2.0及以上版本,可通过迭代行快速完成:

import pandas as pd

output_df = pd.DataFrame({
    'label': ['label1', 'label2', 'label3'],
    'pred': ['val1', ['str1', 'str2'], 'foo'],
    'gt': ['val11', ['str1', 'str3', 'str4'], 'box']
})

# 遍历每行处理,非列表转单元素列表后补全对齐
rows = []
for _, row in output_df.iterrows():
    pred = row['pred'] if isinstance(row['pred'], list) else [row['pred']]
    gt = row['gt'] if isinstance(row['gt'], list) else [row['gt']]
    max_len = max(len(pred), len(gt))
    pred += [None]*(max_len - len(pred))
    gt += [None]*(max_len - len(gt))
    rows.append(pd.DataFrame({'label': row['label'], 'pred': pred, 'gt': gt}))

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

# 可选:添加引号
final_df[['pred', 'gt']] = final_df[['pred', 'gt']].applymap(lambda x: f"'{x}'" if pd.notna(x) else x)

print(final_df)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:37:54