#python #pandas #aggregate
#python #pandas #агрегировать
Вопрос:
У меня есть фрейм данных, который имеет одинаковые значения в разных его частях, они могут находиться в разных строках и разных столбцах. Например, у него один и тот же адрес электронной почты в 2 разных столбцах, и я хочу получить идентификаторы 2 разных строк с этим письмом.
test1 = pd.DataFrame([{'id': 'iii1', 'phone': 'aaa1', 'email': 'qqq1', 'phone2': 'bbb1', 'email2': 'sss1'},
{'id': 'iii2', 'phone': 'aaa2', 'email': 'qqq2', 'phone2': 'aaa1', 'email2': 'sss2'},
{'id': 'iii3', 'phone': 'aaa3', 'email': 'qqq3', 'phone2': 'bbb3', 'email2': 'sss3'},
{'id': 'iii4', 'phone': 'aaa4', 'email': 'qqq4', 'phone2': 'bbb4', 'email2': 'qqq3'},
{'id': 'iii5', 'phone': 'aaa5', 'email': 'qqq5', 'phone2': 'bbb5', 'email2': 'sss5'},
{'id': 'iii6', 'phone': 'aaa6', 'email': 'qqq6', 'phone2': 'bbb6', 'email2': 'qqq1'}])
Я попытался сделать это с помощью следующих шагов:
- расплавить столбцы
test2 = pd.melt(
test1, id_vars=['id'],
value_vars=['phone', 'email', 'phone2', 'email2']
).sort_values(by=['id'], ascending=False).reset_index(drop=True)
- группировать по расплавленным значениям:
def testf(ser):
uniqs = pd.unique(ser.values.ravel()).tolist()
uniqs_len = len(uniqs)
if uniqs_len > 1:
return uniqs
else:
return 'only 1, doesnt interesting'
test3 = test2.groupby('value')['id'].apply(testf).reset_index()
Итак, наконец, после этих шагов я получил:
что почти то, что я хочу, но ожидаемый результат должен быть:
[iii1,iii2,iii6]; [iii3,iii4]
Я думаю, что другим способом может быть слияние, но я не знаю, как это реализовать.
Ответ №1:
Ваша проблема — проблема с сетью. Попробуйте networkx
:
import networkx as nx
test2 = (test1.melt('id')
.loc[lambda x: x.duplicated('value',keep=False)]
)
# merge on `value` to connect the id's with same `value`
G = nx.from_pandas_edgelist(test2.merge(test2, on=['value']),
source='id_x', target='id_y')
# output
list(nx.connected_components(G))
Вывод:
[{'iii1', 'iii2', 'iii6'}, {'iii3', 'iii4'}]
Комментарии:
1. Большое спасибо, это работает как по волшебству! Я думал о самостоятельном объединении, но это выглядело более сложным. Честно говоря, никогда не слышал о networkx, отличная функция. И спасибо, что сделали мой код чище 🙂