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

如何对Pandas DataFrame按邮箱和角色分组并编码组织列?

问题描述

现有如下Pandas DataFrame:

import pandas as pd

df = pd.DataFrame({
    'Name': ['John', 'Mary', 'Mark', 'Sarah', 'John', 'Sarah', 'John'],
    'Email': ['john@example.com', 'mary@example.com', 'mark@example.com', 'sarah@example.com', 'john@example.com', 'sarah@example.com', 'john@example.com'],
    'Role_Name': ['Admin', 'User', 'Admin', 'User', 'Admin', 'Admin', 'User'],
    'Last_Login': ['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04', '2022-01-01', '2022-01-05', '2022-01-06'],
    'Organization_Name': ['Org1', 'Org2', 'Org1', 'Org2', 'Org2', 'Org2', 'Org3'],
    'Created_By_Name': ['SuperUser', 'SuperUser', 'SuperUser2', 'SuperUser2', 'SuperUser', 'SuperUser', 'Eve'],
    'Modified_By_Name': ['SuperUser', 'SuperUser', 'SuperUser2', 'SuperUser2', 'SuperUser', 'SuperUser2', 'SuperUser2']
})

需求说明:

  • 每一行对应Email和Role_Name的唯一组合(例如John会有两行,分别对应Admin和User角色)
  • 将Organization_Name列转换为多列(每个组织对应一列),用户拥有该组织权限则值为1,否则为0
  • 注意:此需求不同于pd.get_dummies,同一用户-角色组合可对应多个组织,不能拆分成多行

最终期望的DataFrame如下:

df_result = pd.DataFrame({
    'Name': ['John', 'Mary', 'Mark', 'Sarah', 'Sarah', 'John'],
    'Email': ['john@example.com', 'mary@example.com', 'mark@example.com', 'sarah@example.com', 'sarah@example.com', 'john@example.com'],
    'Role_Name': ['Admin', 'User', 'Admin', 'User', 'Admin', 'User'],
    'Last_Login': ['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04', '2022-01-05', '2022-01-06'],
    'Created_By_Name': ['SuperUser', 'SuperUser', 'SuperUser2', 'SuperUser2', 'SuperUser', 'SuperUser2'],
    'Modified_By_Name': ['SuperUser', 'SuperUser', 'SuperUser2', 'SuperUser2', 'SuperUser2', 'SuperUser2'],
    'Org1': [1, 0, 1, 0, 0, 0],
    'Org2': [1, 1, 0, 1, 1, 0],
    'Org3': [0, 0, 0, 0, 0, 1]
})
解决方案

方法一:分组聚合+独热编码

通过分组保留唯一的Email-Role组合,再对组织列进行编码:

import pandas as pd

# 原始DataFrame(略,同问题描述)

# 1. 分组聚合,获取基础信息和每个分组的组织列表
grouped = df.groupby(['Email', 'Role_Name'], as_index=False).agg(
    Name=('Name', 'first'),
    Last_Login=('Last_Login', 'first'),
    Created_By_Name=('Created_By_Name', 'first'),
    Modified_By_Name=('Modified_By_Name', 'first'),
    Organizations=('Organization_Name', lambda x: list(x.unique()))
)

# 2. 将组织列表转换为独热编码列
org_dummies = grouped['Organizations'].str.join('|').str.get_dummies()

# 3. 合并基础信息和编码列,删除临时字段
result = pd.concat([grouped.drop('Organizations', axis=1), org_dummies], axis=1)

# 调整列顺序匹配目标结果(可选)
result = result[['Name', 'Email', 'Role_Name', 'Last_Login', 'Created_By_Name', 'Modified_By_Name', 'Org1', 'Org2', 'Org3']]

print(result)

代码说明:

  • 以Email+Role_Name分组,确保每行是唯一组合
  • 聚合函数first用于提取同一分组下的唯一字段值(根据目标结果,这些字段在分组内一致)
  • lambda x: list(x.unique())收集分组内所有不重复的组织
  • str.join('|').str.get_dummies()自动生成组织列,存在则为1,否则为0

方法二:使用pivot_table实现

通过设置正确的索引和聚合逻辑,直接生成目标结构:

import pandas as pd

# 原始DataFrame(略,同问题描述)

# 生成透视表
pivot_result = df.pivot_table(
    index=['Email', 'Role_Name', 'Name', 'Last_Login', 'Created_By_Name', 'Modified_By_Name'],
    columns='Organization_Name',
    aggfunc=lambda x: 1 if len(x) > 0 else 0,
    fill_value=0
).reset_index()

# 调整列名和顺序
pivot_result.columns = pivot_result.columns.droplevel(0)
pivot_result = pivot_result.rename(columns={'': 'Email', '': 'Role_Name', '': 'Name', '': 'Last_Login', '': 'Created_By_Name', '': 'Modified_By_Name'})
pivot_result = pivot_result[['Name', 'Email', 'Role_Name', 'Last_Login', 'Created_By_Name', 'Modified_By_Name', 'Org1', 'Org2', 'Org3']]

print(pivot_result)

代码说明:

  • 将非组织字段设为索引,保证唯一组合
  • 以Organization_Name为列,每个组织单独成列
  • 聚合函数判断分组是否包含该组织,存在则标记为1
  • fill_value=0填充未拥有的组织值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:33:18