在Python中为非有序序列创建不同的集群

2024-10-06 18:20:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据框,在第一列中包含人的ID。每个人最多可以有3个其他人被分配到一个具有唯一性的组(或簇)。一个人的相关“CO\u ID”存储在其他3列中。如果一个人是单独的,也就是说,没有其他人分配给他,不管怎样,它应该被认为是在一个人的集群中,其他列的值是nan。这同样适用于只分配给另一个人的人,例如:在这种情况下,一列包含“CO\u ID”,而另两列为nan。你知道吗

我想知道如何通过一个称为“CLUSTER”的附加列将这些(通过已经明确确定的CO\u ID列)集群分配给每个ID?有预构建功能吗?你知道吗

从所提供的示例数据中可以明显看出,“cou ID”的顺序并不重要(对于ID=ID1,cou ID1=ID2和cou ID2=ID3或cou ID1=ID3和cou 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

Tags: idnpnanid3id2c2coid1
1条回答
网友
1楼 · 发布于 2024-10-06 18:20:03

按行应用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')

相关问题 更多 >