查找共享共同元素的行

时间:2020-09-25 22:55:15

标签: python numpy graph-theory

我有一个2D numpy数组,其中每行包含2个整数。我想找到属于共享公共元素的行的所有元素组(也就是边缘列表数组中图的连接组件)。例如,对于数组:

[[ 0  4]
 [ 0  7]
 [ 1  2]
 [ 1 13]
 [ 2  1]
 [ 2  9]
 [ 3 14]
 [ 3 16]
 [ 4  0]
 [ 4  5]
 [ 5  4]
 [ 5  6]
 [ 6  5]
 [ 6  7]
 [ 7  0]
 [ 7  6]]

将包含组

[[ 0  4  5  6  7]
 [ 1  2 13  9]
 [ 3 14 16]]

3 个答案:

答案 0 :(得分:2)

如果可以使用库,请假设您的数组为slotTexture.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST; (请注意,您不能将组件作为numpy数组使用,因为它们可以是numpy中不存在的非矩形数组,因此将它们作为集合输出) :

a

如果您需要一个没有额外库的纯numpyic解决方案,请查看以下通用解决方案: https://stackoverflow.com/a/61764414/4975981

答案 1 :(得分:1)

我确信有更快的方法,并且我不学习图论,但是您可以从这里开始;

x = [[ 0,  4],
 [ 0,  7],
 [ 1,  2],
 [ 1, 13],
 [ 2,  1],
 [ 2,  9],
 [ 3, 14],
 [ 3, 16],
 [ 4,  0],
 [ 4,  5],
 [ 5,  4],
 [ 5,  6],
 [ 6,  5],
 [ 6,  7],
 [ 7,  0],
 [ 7,  6]]

nodes = list(set([item for sublist in x for item in sublist]))
grps = {n: g for n, g in zip(nodes, range(len(nodes)))}

for v in x:
    t = grps[v[0]]
    f = grps[v[1]]
    if t != f:
        for n in grps:
            if grps[n] == f:
                grps[n] = t

ret = [[k for k, v in grps.items() if v==g] for g in set(grps.values())]
print(ret)

答案 2 :(得分:1)

根据图论,您需要从一组边线创建一个图,然后找到该图的连接组件。基于纯df.join(df.groupBy('date', 'hos').pivot('time').agg(first('topwait').alias('topwait')), ['date', 'hos'], 'left') \ .show() +---------+---+-----+-------+-----+-----+ | date|hos| time|topwait|11:00|12:00| +---------+---+-----+-------+-----+-----+ |19/9/2020|KHW|11:00| 5| 5| 1| |19/9/2020|CCM|11:00| 6| 6| 2| |19/9/2020|HHJ|11:00| 7| 7| 4| |19/9/2020|KHW|12:00| 1| 5| 1| |19/9/2020|CCM|12:00| 2| 6| 2| |19/9/2020|HHJ|12:00| 4| 7| 4| |22/9/2020|KHW|11:00| 9| 9| 4| |22/9/2020|CCM|11:00| 9| 9| 3| |22/9/2020|HHJ|11:00| 9| 9| 2| |22/9/2020|KHW|12:00| 4| 9| 4| |22/9/2020|CCM|12:00| 3| 9| 3| |22/9/2020|HHJ|12:00| 2| 9| 2| +---------+---+-----+-------+-----+-----+ 的解决方案对我来说似乎太难了,但是您仍然可以使用用C编写的numpy使其达到C级(与纯Python的igraph不同)。您需要先安装networkx

民事案件

python-igraph方法返回igraph.Graph.clusters()类的特殊实例,可以将其转换为igraph.clustering.VertexClustering

list

import igraph arr = np.array([[0, 4], [0, 7], [1, 2], [1, 9], [2, 1], [2, 8], [3, 10], [3, 11], [4, 0], [4, 5], [5, 4], [5, 6], [6, 5], [6, 7], [7, 0], [7, 6]]) g = ig.Graph() g.add_vertices(12) g.add_edges(arr) i = g.clusters() print(list(i)) #output: [[0, 4, 5, 6, 7], [1, 2, 8, 9], [3, 10, 11]] 还支持绘制这些连接的组件,就像在igraph中所做的那样,但是您可能需要从非官方二进制文件下载networkx并安装它才能解锁pycairo选项:

igraph.plot

enter image description here

一般情况

请注意,如果使用初始数组而不是普通数组,则pal = ig.drawing.colors.ClusterColoringPalette(len(i)) #passing a number of colors color = pal.get_many(i.membership) # a list of color codes for each vertex ig.plot(g, bbox = (200, 100), vertex_label=g.vs.indices, vertex_color = color, vertex_size = 12, vertex_label_size = 8) 会抛出igraph。那是因为应该在添加边之前声明每个顶点,并且不允许所有顶点都有缺失的数字(事实上,这是允许的,但是重新索引是静默完成的,并且可以使用'name'属性访问旧名称)。可以通过编写自定义函数从重新标记的边创建图形来解决此问题:

InternalError

在输出中使用了新标签(因此使它不正确),但是仍然可以像这样访问旧标签:

def create_from_edges(edgelist):
    g = ig.Graph()
    u, inv = np.unique(edgelist, return_inverse=True)
    e = inv.reshape(edgelist.shape)
    g.add_vertices(u) #add vertices, not reindexed
    g.add_edges(e) #add edges, reindexed
    return g

arr = np.array([[0, 4], [0, 7], [1, 2], [1, 13], [2, 1], [2, 9], [3, 14], 
                [3, 16], [4, 0], [4, 5], [5, 4], [5, 6], [6, 5], [6, 7], [7, 0], [7, 6]])
g = create_from_edges(arr)
i = g.clusters()
print(list(i))
#output: [[0, 4, 5, 6, 7], [1, 2, 8, 9], [3, 10, 11]]

它们可用于预览原始图形(print('new_names:', g.vs.indices) print('old_names:', g.vs['name']) >>> new_names: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] >>> old_names: [0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 14, 16] 现在有所不同):

vertex_label

enter image description here

最后,您需要使用旧的顶点名称来修复输出。可以这样完成:

pal = ig.drawing.colors.ClusterColoringPalette(len(i)) #passing a number of colors 
color = pal.get_many(i.membership) ##a list of color codes for each vertex
ig.plot(g,  bbox = (200, 100), vertex_label=g.vs['name'], 
        vertex_color = color, vertex_size = 12, vertex_label_size = 8)