Группировать совпавшие пары по нескольким столбцам Python - PullRequest
2 голосов
/ 10 февраля 2020

Спасибо за чтение.

У меня есть кадр данных, который выглядит следующим образом:

Col_A  Col_B   Col_C  Col_D  Col_E  
 1     2       null   null   null  
 1     null    3      null   null  
 null  2       3      null   null  
 null  2       null   4      null  
 1     null    null   null   5 

Каждая строка состоит из совпадения между двумя идентификаторами (например, ID1 из Col_A соответствует ID2 из Col_B в первом ряду).

В приведенном выше примере подключены все 5 идентификаторов (1 подключен к 2, 2 к 3, от 2 до 4, от 1 до 5). Поэтому я хочу создать новый столбец, который объединяет все эти строки вместе, чтобы я мог легко получить доступ к каждой группе совпадающих пар:

Col_A  Col_B   Col_C  Col_D  Col_E  Group ID
 1     2       null   null   null      1
 1     null    3      null   null      1
 null  2       3      null   null      1
 null  2       null   4      null      1
 1     null    null   null   5         1

Я еще не смог найти аналогичный вопрос, но извинения если это дубликат Заранее большое спасибо за любые советы.

1 Ответ

2 голосов
/ 10 февраля 2020

Как подсказывают @YOBEN_S и @QuangHoang, вы можете использовать библиотеку networkx и компоненты, связанные с теорией графов , вот так.

Учитывая df,

df = pd.DataFrame({'Col_A': {0: 1.0, 1: 1.0, 2: np.nan, 3: np.nan, 4: 1.0, 5: np.nan},
 'Col_B': {0: 2.0, 1: np.nan, 2: 2.0, 3: 2.0, 4: np.nan, 5: np.nan},
 'Col_C': {0: np.nan, 1: 3.0, 2: 3.0, 3: np.nan, 4: np.nan, 5: np.nan},
 'Col_D': {0: np.nan, 1: np.nan, 2: np.nan, 3: 4.0, 4: np.nan, 5: np.nan},
 'Col_E': {0: np.nan, 1: np.nan, 2: np.nan, 3: np.nan, 4: 5.0, 5: np.nan},
 'Col_F': {0: np.nan, 1: np.nan, 2: np.nan, 3: np.nan, 4: np.nan, 5: 6.0},
 'Col_G': {0: np.nan, 1: np.nan, 2: np.nan, 3: np.nan, 4: np.nan, 5: 7.0}})

|    |   Col_A |   Col_B |   Col_C |   Col_D |   Col_E |   Col_F |   Col_G |
|---:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|
|  0 |       1 |       2 |     nan |     nan |     nan |     nan |     nan |
|  1 |       1 |     nan |       3 |     nan |     nan |     nan |     nan |
|  2 |     nan |       2 |       3 |     nan |     nan |     nan |     nan |
|  3 |     nan |       2 |     nan |       4 |     nan |     nan |     nan |
|  4 |       1 |     nan |     nan |     nan |       5 |     nan |     nan |
|  5 |     nan |     nan |     nan |     nan |     nan |       6 |       7 |

Use

import networkx as nx
d_edge = df.apply(lambda x: x.dropna().to_numpy(), axis=1)
G = nx.from_edgelist(d_edge.to_numpy().tolist())
cc_list = list(nx.connected_components(G))
df['groupid'] = d_edge.apply(lambda  x: [n for n, i in enumerate(cc_list) if x[0] in i][0] + 1)
df

Выход:

|    |   Col_A |   Col_B |   Col_C |   Col_D |   Col_E |   Col_F |   Col_G |   groupid |
|---:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|----------:|
|  0 |       1 |       2 |     nan |     nan |     nan |     nan |     nan |         1 |
|  1 |       1 |     nan |       3 |     nan |     nan |     nan |     nan |         1 |
|  2 |     nan |       2 |       3 |     nan |     nan |     nan |     nan |         1 |
|  3 |     nan |       2 |     nan |       4 |     nan |     nan |     nan |         1 |
|  4 |       1 |     nan |     nan |     nan |       5 |     nan |     nan |         1 |
|  5 |     nan |     nan |     nan |     nan |     nan |       6 |       7 |         2 |
...