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

如何合并与拆分DataFrame行?处理同名不同用户及重复数据

解决思路与实现代码

核心问题分析

你的需求本质是区分"同名同用户"和"同名不同用户",并合并同一用户的分散信息:

  • 同名同用户:不同行属于同一个人,需合并所有非缺失信息
  • 同名不同用户:姓名相同但属于不同个体(如原数据中的两个"C"),需拆分为独立行

邮箱是最可靠的用户唯一标识,因此我们以邮箱为核心分组依据,结合姓名关联无邮箱的行,最终合并信息。

实现步骤与代码

1. 构造示例数据

import pandas as pd
from pandas import NaT

# 还原你的原DataFrame
df = pd.DataFrame({
    'Name': ['A', 'B', 'C', 'D', 'B', 'D', 'B', 'C'],
    'Mail': ['A@gmail.com', None, 'C@gmail.com', None, None, 'D@gmail.com', 'B@gmail.com', 'C2@gmail.com'],
    'Birthday': ['1-1-1990', NaT, '1-1-1985', '1-1-1980', '1-1-1995', NaT, NaT, '1-1-1970'],
    'Genre': ['M', 'F', 'M', 'I', 'I', 'M', 'I', 'F'],
    'Subscription': ['Y', 'N', 'Y', 'N', 'N', 'Y', 'Y', 'N'],
    'Age': [33, None, 38, 43, 27, None, None, 53],
    'Comments': ['-'] * 8
})

2. 关联无邮箱行到对应用户

通过姓名匹配已有邮箱,填充无邮箱行的邮箱字段:

# 创建「姓名→邮箱」映射(仅保留每个姓名对应的非空邮箱)
name_mail_map = df[df['Mail'].notna()].drop_duplicates('Name').set_index('Name')['Mail'].to_dict()

# 填充无邮箱行的邮箱
df['Mail'] = df['Mail'].fillna(df['Name'].map(name_mail_map))

# 处理仍无邮箱的行(生成临时唯一标识,避免丢失)
mask = df['Mail'].isna()
df.loc[mask, 'Mail'] = df.loc[mask, 'Name'] + '_' + df.loc[mask, 'Birthday'].astype(str)

3. 定义合并规则函数

合并同一用户的多行,保留所有非缺失值(优先用前后填充补全有效信息,最后一行即为合并结果):

def merge_user_group(group):
    # 前后填充补全缺失值,取最后一行作为合并结果
    return group.ffill().bfill().iloc[-1]

4. 按邮箱分组合并

# 按邮箱分组合并用户信息
merged_df = df.groupby('Mail').apply(merge_user_group).reset_index(drop=True)

# 将邮箱前缀作为新姓名(区分同名不同用户)
merged_df['Name'] = merged_df['Mail'].str.split('@').str[0]

# 调整列顺序与期望结果一致
merged_df = merged_df[['Name', 'Mail', 'Birthday', 'Genre', 'Subscription', 'Age', 'Comments']]

5. 最终结果

Name Mail          Birthday Genre Subscription Age Comments
0    A    A@gmail.com   1-1-1990 M     Y            33  -
1    B    B@gmail.com   1-1-1995 F     Y            27  -
2    C    C@gmail.com   1-1-1985 M     Y            38  -
3    C2   C2@gmail.com  1-1-1970 F     N            53  -
4    D    D@gmail.com   1-1-1980 M     Y            43  -

自定义调整说明

如果需要针对特定列修改合并规则(如Age取最大值、Genre取出现次数最多的值),可以修改merge_user_group函数:

def merge_user_group(group):
    merged = group.copy()
    # 示例:Age取最大值
    merged['Age'] = merged['Age'].max()
    # 示例:Genre取出现次数最多的值
    merged['Genre'] = merged['Genre'].mode()[0]
    # 其他列保留非空值
    for col in merged.columns.drop(['Age', 'Genre']):
        merged[col] = merged[col].ffill().bfill().iloc[-1]
    return merged.iloc[-1]

内容的提问来源于stack exchange,提问作者Pablo Moreira Garcia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:55:25