【问题标题】:Sum the edge in adjacency matrix according to group label in numpy array根据numpy数组中的组标签对邻接矩阵中的边求和
【发布时间】:2020-10-30 14:22:47
【问题描述】:

例如,我得到了对称邻接矩阵(无自环),即

A = 
[
[0, 1, 1, 0, 0],
[1, 0, 1, 0, 1],
[1, 1, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 1, 0, 1, 0]]

然后,我得到了一个与此图相关联的集群标签 i 数组,即

cluster = [1,1,2,2,3]

表示节点1和节点2在同一个组,节点3和节点4在同一个组,节点5在一个独立的组。

问题是我怎样才能得到组内和组间的边的总和,

组内:表示节点之间共享相同簇标签的边,例如节点1和节点2在同一个组中,因此它们的和为1,节点3和节点4相同。对于节点 5,其为 0。

组间:表示共享不同集群标签的节点之间的边,例如组1和组2,表示节点1节点3,节点1节点4,节点2节点3,节点的边之和2 节点 4。答案是组 1 和组 2 之间的 2。

然后返回一个包含结果的二维对称数组,即

[[1,2,1],
[2,1,1],
[1,1,0]]

【问题讨论】:

    标签: python numpy igraph numpy-ndarray adjacency-matrix


    【解决方案1】:

    你可以使用矩阵代数;

    cluster = np.array(cluster)
    # create cluster-node adjacency matrix
    aux = np.identity(cluster.max(),int)[cluster-1]
    # we can now count by multiplying
    out = aux.T@A@aux
    # fix diagonal (which was counted twice)
    np.einsum("ii->i",out)[...] //= 2
    out
    # array([[1, 2, 1],
    #        [2, 1, 1],
    #        [1, 1, 0]])
    

    为了加快速度,我们可以将矩阵乘积替换为 (1) 如果节点按集群排序:

    boundaries = np.diff(cluster,prepend=-1).nonzero()[0]
    out =  np.add.reduceat(np.add.reduceat(A,boundaries,1),boundaries,0)
    

    (2) 如果不是:

    nc = cluster.max()
    out = np.zeros((nc,nc),int)
    np.add.at(out,(cluster[:,None]-1,cluster-1),A)
    

    【讨论】:

    • @NicolasH 我添加了一些 cmets,希望对您有所帮助。
    • @PaulPanzer 虽然,我认为这比其他方法慢得多(但更紧凑/可读)。我很好奇我的理解是否正确?
    • @Ehsan,我想是的。可以尝试使用稀疏矩阵。我会尝试编写一个更快的混合版本。
    【解决方案2】:

    这将返回一个数组,其中元素为[i,j],对应的簇ij 的边的总和:

    n = cluster.max()
    degrees = np.zeros((n,n))
    idx = [np.where(cluster==i)[0] for i in np.arange(n)+1]
    for i in range(n):
      degrees[i,i] = A[np.ix_(idx[i],idx[i])].sum()/2
      for j in range(i):
        degrees[i,j] = degrees[j,i] = A[np.ix_(idx[i],idx[j])].sum()
    

    输出:

    [[1. 2. 1.]
     [2. 1. 1.]
     [1. 1. 0.]]
    

    您也可以使用 itertools,但我认为这可能更快。

    【讨论】:

    • @NicolasH 欢迎您。我个人喜欢 Paul 的回答,因为它更抽象,但如果您的图表足够大/您关心性能,我希望这会更快(并且内存效率更高)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多