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

Pandas按标识符分组聚合字符串变量并处理多值与空单元格

解决DataFrame按ID合并并处理多值列的问题

我明白你现在需要处理一个带重复ID和大量空值的DataFrame,核心需求是把同一ID的所有非空值整合到一行,同时对多出来的条目生成带后缀的标识来区分。下面给你提供一套基于Pandas的实用解决方案,完全贴合你的场景。

首先,先把你给出的示例数据转换成可复现的测试DataFrame,方便你直接验证:

import pandas as pd
import numpy as np

# 构造和示例匹配的测试数据
data = [
    ["Tom", "sarah", "mike", np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
    ["Tom", np.nan, np.nan, "john", "john", np.nan, np.nan, np.nan, np.nan],
    ["Gen", "paul", np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
    ["Gen", np.nan, np.nan, "sandra", np.nan, np.nan, np.nan, np.nan, np.nan],
    ["Gen", np.nan, np.nan, "lara", "lara", "lara", "lara", np.nan, np.nan],
    ["Gen", np.nan, np.nan, "mike", "mike", np.nan, np.nan, np.nan, np.nan],
    ["Lara", "bill", "bill", "bill", np.nan, np.nan, np.nan, np.nan, np.nan],
    ["Lara", np.nan, np.nan, "josh", "josh", np.nan, np.nan, np.nan, np.nan],
    ["Lara", np.nan, np.nan, "kevin", "kevin", np.nan, np.nan, np.nan, np.nan]
]

df = pd.DataFrame(data, columns=["ID", "name1", "name2", "name3", "name4", "name5", "name6", "name7", "name8"])

方案一:把同一ID的所有非空值合并到一行,生成带序号后缀的列

这个方案适合你需要把同一ID的所有非空内容集中到一行,按顺序用name_1、name_2这样的后缀区分的场景:

def process_single_id_group(group):
    # 收集当前ID分组下所有name列的非空值,按顺序排列
    all_non_null_values = group.filter(like='name').stack().tolist()
    # 生成带序号的新列名
    new_col_names = [f"name_{i+1}" for i in range(len(all_non_null_values))]
    # 返回包含ID和所有非空值的Series,用于后续合并
    return pd.Series([group['ID'].iloc[0]] + all_non_null_values, index=["ID"] + new_col_names)

# 按ID分组处理,合并结果并重置索引
final_result = df.groupby('ID', group_keys=False).apply(process_single_id_group).reset_index(drop=True)

代码逻辑说明:

  • group.filter(like='name'):只保留当前分组中所有以name开头的列,过滤掉ID列
  • .stack():把列维度的数据转成行维度,自动跳过空值,快速集中所有非空的name值
  • 生成name_1、name_2这类后缀列名,保证每个非空值都有唯一对应的列
  • 通过groupby.apply把每个ID的处理结果合并成完整的DataFrame

处理后的结果示例:

IDname_1name_2name_3name_4name_5name_6name_7name_8
Genpaulsandralaralaralaralaramikemike
LarabillbillbilljoshjoshkevinkevinNaN
TomsarahmikejohnjohnNaNNaNNaNNaN

方案二:保留原始列名,仅对同一列的多值生成带后缀的新列

如果你的需求是保留原始列的对应关系,只有当同一ID的同一原始列(比如name1)有多个非空值时,才生成name1_2这类后缀列,用下面的代码:

# 把宽表转成窄表,仅保留非空值
melted_df = df.melt(id_vars='ID', var_name='original_col', value_name='value').dropna()
# 给每个ID的同一原始列的条目加序号后缀
melted_df['suffix'] = melted_df.groupby(['ID', 'original_col']).cumcount() + 1
# 生成新列名:单值用原始列名,多值加后缀
melted_df['new_col'] = melted_df.apply(
    lambda x: f"{x['original_col']}_{x['suffix']}" if x['suffix'] > 1 else x['original_col'],
    axis=1
)
# 转回宽表得到最终结果
final_result = melted_df.pivot(index='ID', columns='new_col', values='value').reset_index()

这个方案更适合需要追溯原始列对应关系的场景,不会打乱原有列的命名逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:49:06