在Numpy中将3列矩阵转换为N x N矩阵

时间:2016-03-15 13:35:09

标签: python numpy matrix

我有一个包含3列的2D numpy数组。第1列和第2列是ID之间的连接列表。第3列是该连接的强度。我想将这3列矩阵转换为加权adjacency matrix(N×N矩阵,其中单元格表示每个ID之间的连接强度)。

我已在下面的代码中完成此操作。 matrix是3列2D数组,t1是加权邻接矩阵。我的问题是这个代码非常慢,因为我使用的是嵌套for循环。我熟悉执行此操作的pandas函数melt,但我无法使用pandas。是否有更快的实施不使用pandas

import numpy as np
a = np.arange(2000)
np.random.shuffle(a)
b = np.arange(2000)
np.random.shuffle(b)
c = np.random.rand(2000,1)

matrix = np.column_stack((a,b,c))

#get unique value list of nm
flds = list(np.unique(matrix[:,0]))
flds.extend(list(np.unique(matrix[:,1])))
flds = np.asarray(flds)
flds = np.unique(flds)

#make lookup dict
lookup = dict(zip(np.arange(0,len(flds)), flds))
lookup_rev = dict(zip(flds, np.arange(0,len(flds))))

#make empty n by n matrix with unique lists
t1 = np.zeros([len(flds) , len(flds)])

#map values into the n by n matrix and make the rest 0
'''this takes a long time to run'''
#iterate through rows
for i in np.arange(0,len(lookup)):
    #iterate through columns
    for k in np.arange(0,len(lookup)):
        val = matrix[(matrix[:,0] == lookup[i]) & (matrix[:,1] == lookup[k])][:,2]  
        if val:
            t1[i,k] = sum(val)

3 个答案:

答案 0 :(得分:2)

假设我正确理解了问题并且val是标量,您可以使用向量化方法,包括使用zeros然后indexing进行初始化,就像这样 -

out = np.zeros((len(flds),len(flds)))
out[matrix[:,0].astype(int),matrix[:,1].astype(int)] = matrix[:,2]

请注意,根据我的观察,您似乎可以避免使用lookup

答案 1 :(得分:1)

你可以得到的主要加速是不迭代NxN矩阵的每个元素,而是通过你的连接列表迭代,这个更小。

我试着简化你的代码。它使用list.index方法,这可能很慢,但它仍然应该比你拥有的更快。

import numpy as np
a = np.arange(2000)
np.random.shuffle(a)
b = np.arange(2000)
np.random.shuffle(b)
c = np.random.rand(2000,1)

matrix = np.column_stack((a,b,c))

lookup = np.unique(matrix[:,:2]).tolist() # You can call unique only once

t1 = np.zeros((len(lookup),len(lookup)))

for i,j,val in matrix:
    t1[lookup.index(i),lookup.index(j)] = val # Fill the matrix

答案 2 :(得分:1)

您只需要迭代一次矩阵:

import numpy as np

size = 2000

a = np.arange(size)
np.random.shuffle(a)
b = np.arange(size)
np.random.shuffle(b)
c = np.random.rand(size,1)

matrix = np.column_stack((a,b,c))

#get unique value list of nm
fields = np.unique(matrix[:,:2])
n = len(fields)

#make reverse lookup dict
lookup = dict(zip(fields, range(n)))

#make empty n by n matrix
t1 = np.zeros([n, n])

for src, dest, val in matrix:
    i = lookup[src]
    j = lookup[dest]

    t1[i, j] += val