Сложная дедупликация - PullRequest
       2

Сложная дедупликация

0 голосов
/ 25 октября 2018

У меня большой фрейм данных, и я хочу в основном создать «уникальный идентификатор» для каждого отдельного человека.Соответствующий столбец - это столбец «электронная почта», но он затруднен форматированием: каждый человек может иметь несколько электронных писем.Пример кадра ниже:

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

Мой мозг вроде как взрывается, выясняякак это сделать, используя для циклов, так что я надеюсь, что есть более простой способ (плюс, я много раз перебираю df.index, который, как мне говорят, является дурным тоном и невероятно медленным независимо).Есть ли функция, которая могла бы что-то сделать, если бы я сделал несколько столбцов электронной почты с отдельными элементами электронной почты?

Спасибо!

РЕДАКТИРОВАТЬ: Извинения за опечатку в третьей строке электронной почты-почта, это было исправлено.

1 Ответ

0 голосов
/ 25 октября 2018

Предполагается, что в общей электронной почте есть опечатка, это многоэтапная проблема, которая включает библиотеки pandas и networkx, это проблема сети, и я черпал вдохновение в этих 2 вопросах проблема сети и проблема разделения списка :

(1) Разбить электронные письма на списки
(2) Разбить столбец электронной почты
(3) Создать пограничные списки пользователей с одинаковыми электронными письмами
(4) Создайте сеть с этим крайним списком
(5) Извлеките различные подграфы сети, которые будут представлять ваши уникальные идентификаторы
(6) Назначьте эти уникальные идентификаторы оригинальным людям

(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) Извлечение различных подграфов сети, которые будут представлять ваши уникальные идентификаторы

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

(6) Назначить эти уникальные идентификаторы оригинальным людям

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...