Создать отдельный кластер для неупорядоченных последовательностей в Python - PullRequest
0 голосов
/ 11 ноября 2018

У меня есть фрейм данных, содержащий "ID" людей в первом столбце. Каждый человек может иметь до 3 других людей, с которыми он назначен в уникальную группу (или кластер). Связанные "CO_ID" человека хранятся в 3 других столбцах. Если человек один, т. Е. Ему не назначены другие лица, его следует рассматривать так, как если бы он находился в кластере из одного человека, так как значения других столбцов не совпадают. То же самое относится к лицам, которые назначены только, например, еще один человек: в этом случае один столбец содержит «CO_ID», в то время как два других столбца обозначены как nan.

Интересно, как я могу назначить эти (через уже определенные столбцы CO_ID) кластеры каждому идентификатору через дополнительный столбец, называемый "CLUSTER"? Есть ли для этого функция предварительной сборки?

Как видно из приведенных в качестве примера данных, порядок «CO_ID» не важен (для ID = ID1 не имеет значения, если CO_ID1 = ID2 и CO_ID2 = ID3 или CO_ID1 = ID3 и CO_ID2 = ID2).

Входные данные df1 выглядят так:

import pandas as pd
import numpy as np
df1 = pd.DataFrame({'ID' : ['ID1','ID2','ID3','ID4','ID5','ID6','ID7','ID8','ID9','ID10'] ,
                    'CO_ID1' : ['ID2','ID1','ID2','ID6','ID8','ID4','ID4','ID5', np.nan, 'ID4'],
                    'CO_ID2' : ['ID3','ID3','ID1', 'ID7', np.nan, 'ID7','ID6',  np.nan, np.nan, 'ID6'],
                    'CO_ID3' : [np.nan, np.nan, np.nan, 'ID10', np.nan, 'ID10', 'ID10', np.nan, np.nan, 'ID7']})

Out[1]: 

  ID CO_ID1 CO_ID2 CO_ID3 
0   ID1    ID2    ID3    NaN      
1   ID2    ID1    ID3    NaN      
2   ID3    ID2    ID1    NaN      
3   ID4    ID6    ID7   ID10      
4   ID5    ID8    NaN    NaN      
5   ID6    ID4    ID7   ID10      
6   ID7    ID4    ID6   ID10      
7   ID8    ID5    NaN    NaN      
8   ID9    NaN    NaN    NaN      
9  ID10    ID4    ID6    ID7      

И нужные выходные данные df2 выглядят так:

df2 = pd.DataFrame({'ID' : ['ID1','ID2','ID3','ID4','ID5','ID6','ID7','ID8','ID9','ID10'] ,
                    'CO_ID1' : ['ID2','ID1','ID2','ID6','ID8','ID4','ID4','ID5', np.nan, 'ID4'],
                    'CO_ID2' : ['ID3','ID3','ID1', 'ID7', np.nan, 'ID7','ID6',  np.nan, np.nan, 'ID6'],
                    'CO_ID3' : [np.nan, np.nan, np.nan, 'ID10', np.nan, 'ID10', 'ID10', np.nan, np.nan, 'ID7'],
                    'Cluster' : ['C1','C1','C1','C2','C3','C2','C2','C3','C4','C2']})

Out[2]:

  ID CO_ID1 CO_ID2 CO_ID3 Cluster
0   ID1    ID2    ID3    NaN      C1
1   ID2    ID1    ID3    NaN      C1
2   ID3    ID2    ID1    NaN      C1
3   ID4    ID6    ID7   ID10      C2
4   ID5    ID8    NaN    NaN      C3
5   ID6    ID4    ID7   ID10      C2
6   ID7    ID4    ID6   ID10      C2
7   ID8    ID5    NaN    NaN      C3
8   ID9    NaN    NaN    NaN      C4
9  ID10    ID4    ID6    ID7      C2

1 Ответ

0 голосов
/ 11 ноября 2018

Применить frozenset по строкам, чтобы создать отдельные группы, которые можно хэшировать и упорядочивать (поэтому, в какой строке они появляются, не имеет значения). Сгруппируйте их и используйте ngroup для обозначения каждой отдельной группы.

df1['Cluster'] = 'C'+ (df1.groupby(df1.apply(frozenset, 1), sort=False).ngroup()+1).astype('str')

выход

     ID CO_ID1 CO_ID2 CO_ID3 Cluster
0   ID1    ID2    ID3    NaN      C1
1   ID2    ID1    ID3    NaN      C1
2   ID3    ID2    ID1    NaN      C1
3   ID4    ID6    ID7   ID10      C2
4   ID5    ID8    NaN    NaN      C3
5   ID6    ID4    ID7   ID10      C2
6   ID7    ID4    ID6   ID10      C2
7   ID8    ID5    NaN    NaN      C3
8   ID9    NaN    NaN    NaN      C4
9  ID10    ID4    ID6    ID7      C2

Если производительность является проблемой, выполните сортировку с numpy. Нам нужно заменить плавающий NaN на строки, чтобы все значения можно было сравнивать по столбцам.

import numpy as np

d = pd.DataFrame(np.sort(df1.replace(np.NaN, 'NaN').values, 1), index=df1.index)
df1['Cluster'] = 'C'+(d.groupby(d.columns.tolist()).ngroup()+1).astype('str')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...