【问题标题】:A Difficult Deduplication困难的重复数据删除
【发布时间】:2019-03-30 07:57:30
【问题描述】:

我有一个大型数据框,我想基本上为每个单独的人创建一个“唯一标识符”。相关栏是“电子邮件”栏,但由于格式设置困难:每个人可以有多个电子邮件。下面的示例框架:

Name of person ||| E-mail Address
'John Doe'     ||| 'john.c.doe@choo.com'
'Bob Jones'    ||| 'bobbyj@aboy.net;bob.jones@omic.com'
'Robert Jones' ||| 'robert@mail.com;bobbyj@aboy.net'
'Clara Bit'    ||| 'clara@mail.com'
'John Doe'     ||| 'j.diddy@ack.org;jjd@ila.hun'

我希望有一个字段可以根据电子邮件将人们区分开来:

Name of person ||| person ID
'John Doe'         1
'Bob Jones'        2
'Robert Jones'     2
'Clara Bit'        3
'John Doe'         4

我的大脑有点想知道如何使用 for 循环来做这件事,所以我希望有一种更简单的方法(另外,我在 df.index 上迭代了很多次,我被告知这是不好的形式并且无论如何都非常慢)。如果我用单个电子邮件元素创建多个电子邮件列,是否有可以做某事的功能?

谢谢!

编辑:对电子邮件第三行的错字表示歉意,已修复。

【问题讨论】:

  • 在您当前的示例中,Bob 和 Robert Jones 共享电子邮件,Robert 应该是 bobbyj@aboy.net 吗?
  • 不清楚您是如何将Bob JonesRobert Jones 分组的,它们的email 列中的字段均不匹配。
  • 后一个 aboy.net 电子邮件中缺少 'j' 大概是一个错字
  • 我会使用一个将电子邮件地址映射到 UID 的字典。检查电子邮件是否在 dict 的键中既快速又简单。

标签: python python-3.x pandas dataframe


【解决方案1】:

假设共享邮件有错别字,这是一个涉及pandas和networkx库的多步骤问题,这是一个网络问题,我从network problemsplitting list problem这两个问题中得到灵感:

(1) 将电子邮件发送到列表中
(2) 展开邮件栏
(3) 创建具有相同电子邮件的用户的边缘列表
(4) 使用该边缘列表创建网络
(5) 提取代表您唯一 id 的网络的不同子图
(6) 将那些唯一的 id 分配给原始人

(1) 将电子邮件发送到列表中

import pandas as pd  
df = pd.DataFrame({'name':['John','Bob', 'Rob', 'Clara', 'John'], 'email':['john.c.doe@choo.com','bobby@aboy.net;bob.jones@omic.com','robert@mail.com;bobby@aboy.net','clara@mail.com','j.diddy@ack.org;jjd@ila.hun']}) 
df['email_list'] = df['email'].str.split(';').tolist()

(2) 展开邮件栏

df_emails = df['email_list'].apply(pd.Series).reset_index().melt(id_vars='index',value_name='email').dropna()[['index', 'email']].set_index('index')

(3) 创建具有相同电子邮件用户的边缘列表

df_emails['email_id'] = df_emails.groupby('email').ngroup()
df_emails = df_emails.reset_index()
network = df_emails.merge(df_emails, on='email_id').drop(columns=['email_id', 'email_x', 'email_y'])

(4) 使用该边缘列表创建网络

import networkx as nx
G = nx.from_pandas_edgelist(network, source='index_x', target='index_y')

(5) 提取网络的不同子图,这些子图将代表您的唯一 ID

l = [list(x.nodes()) for x in nx.connected_component_subgraphs(G)]

(6) 将这些唯一的 id 分配给原始人

d = dict((k, i) for i in range(len(l)) for k in l[i])
df['unique_id'] = df.index.map(d)

最终结果是:

    name    email   email_list  unique_id
0   John    john.c.doe@choo.com [john.c.doe@choo.com]   0
1   Bob bobby@aboy.net;bob.jones@omic.com   [bobby@aboy.net, bob.jones@omic.com]    1
2   Rob robert@mail.com;bobby@aboy.net  [robert@mail.com, bobby@aboy.net]   1
3   Clara   clara@mail.com  [clara@mail.com]    2
4   John    j.diddy@ack.org;jjd@ila.hun [j.diddy@ack.org, jjd@ila.hun]  3

【讨论】:

  • 惊人的答案,非常感谢!测试它有效,现在我只需要坐下来找出原因:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 2011-03-08
  • 2020-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多