Это похоже на проблему с сетью, которую можно решить с помощью networkx
.Нам нужно сформировать сеть из всех cust_id
s, которые связаны либо по электронной почте, либо по телефону.
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
# Generate group numbers for unique phones and e-mails
df['p_gp'] = df.groupby('phone').ngroup()
df['e_gp'] = df.groupby('email').ngroup()
# This will create all pair-wise combinations customer_ids within the same `gp`
def gen_pairs(df, gp_col):
nwk = df[['customer_id', gp_col]].merge(df[['customer_id', gp_col]], on=gp_col).drop(columns=gp_col)
# Removes duplicates, not necessary and slow
#nwk = nwk.assign(dummy = nwk.apply(frozenset,1)).drop_duplicates('dummy').drop(columns='dummy')
return nwk
# All pair-wise combinations of either e-mail or phone
dfn = pd.concat([gen_pairs(df, 'p_gp'), gen_pairs(df, 'e_gp')])
# Create the graph
G = nx.from_pandas_edgelist(dfn, source='customer_id_x', target='customer_id_y')
# Visualize which users are linked:
ax,fig = plt.subplots(figsize=(4,4))
nx.draw(G, node_size=30, with_labels=True, font_size=15, edge_color='#1f77b4')
plt.draw()

Мы можем получить отдельныйгрупп и создать словарь для сопоставления с уникальным идентификатором.
l = [list(x.nodes()) for x in nx.connected_component_subgraphs(G)]
#[['19', '22', 'Guest'], ['23']]
d = dict((k, i) for i in range(len(l)) for k in l[i])
#{'19': 0, '22': 0, '23': 1, 'Guest': 0}
# Finally map the customer_id with the dictionary
df['unique_id'] = df.customer_id.map(d)
transaction_id customer_id phone email p_gp e_gp unique_id
0 1 19 12345 123@email.com 1 0 0
1 2 19 00001 245@gmail.com 0 1 0
2 3 Guest 00001 123@email.com 0 0 0
3 4 22 12345 123@email.com 1 0 0
4 5 23 78900 678@gmail.com 2 2 1