基于 DataFrame 列将数据分组到集群中

Group Data into Clusters Based on DataFrame Columns

我有一个与此类似的数据框 (df):

Node_Start Node_End
1.0 208.0
1.0 911.0
800.0 1.0
3.0 800.0
2.0 511.0
700.0 3.0
200.0 4.0

我想根据 'Node_Start' 和 'Node_End' 列中的值添加一个显示相关聚类的列:

Node_Start Node_End Group
1.0 208.0 1
1.0 911.0 1
800.0 1.0 1
3.0 800.0 1
2.0 511.0 2
700.0 3.0 1
200.0 4.0 3

换句话说,由于 1.0 在 'Node_Start' 和 'Node_End' 中,因此它被分配到第 1 组。由于 800.0 连接到 1.0 和 3.0,这些行也被分配到第 1 组. 2.0 和 511.0 与任何其他行值无关,并分配给第 2 组。200.0 和 4.0 与任何其他行无关,并分配给第 3 组。依此类推...

以下代码实现了预期的结果,但有点笨拙,无法在我的整个数据集上运行,因为它太大(超过 500,000 行)并且我的内核在完成作业之前崩溃

def consolidate(sets):
    # http://rosettacode.org/wiki/Set_consolidation#Python:_Iterative
    setlist = [s for s in sets if s]
    for i, s1 in enumerate(setlist):
        if s1:
            for s2 in setlist[i+1:]:
                intersection = s1.intersection(s2)
                if intersection:
                    s2.update(s1)
                    s1.clear()
                    s1 = s2
    return [s for s in setlist if s]

def group_ids(pairs):
    groups = consolidate(map(set, pairs))
    d = {}
    for i, group in enumerate(sorted(groups)):
        for elem in group:
            d[elem] = i
    return d

这看起来是一个有向图。 Python 有一个很好的处理图形的模块:NetworkX。你的问题似乎是关于寻找连接的组件。

所以我们可以首先构建一个图(对于问题的目的,定向性是无关紧要的,所以我们在这里删除该属性),其中节点是 df 中的元素,边是行。然后使用字典理解创建从节点到组件编号的映射,并将其 map 映射到其中一列:

import networkx as nx
arr = df.to_numpy()    
G = nx.Graph()
G.add_edges_from(arr)

mapping = {node: i for i, component in enumerate(nx.connected_components(G), 1) for node in component}
df['Group'] = df['Node_Start'].map(mapping)

输出:

   Node_Start  Node_End  Group
0         1.0     208.0      1
1         1.0     911.0      1
2       800.0       1.0      1
3         3.0     800.0      1
4         2.0     511.0      2
5       700.0       3.0      1
6       200.0       4.0      3