[英]Speed up operations on a for loop with `coo` matrix and a numpy array in python
我有一个numpy数组和一个coo
矩阵。 我需要基于coo
矩阵中的元素更新numpy数组。 numpy数组和矩阵都非常大,如下所示:
graph_array = [[ 1.0 1.0 5.0 9.0]
[ 2.0 5.0 6.0 5.0]
[ 3.0 5.0 7.0 6.0]]
matrix_coo = (1, 5) 0.5
(2, 8) 0.4
(5, 7) 0.8
我需要做的如下:
如果在阵列中的每个列表中的第二和第三元件即list_graph[i][1][2]
其可以是1,5
, 5,6
或5,7
)等于在一个行和列的一对coo
矩阵(1, 5), (2, 8) or (5, 7)
则与该对关联的值(对于(1, 5)
等于0.5
)必须替换数组中列表中的第四个元素。
我的预期输出将是:
output_array = [[ 1.0 1.0 5.0 0.5]
[ 2.0 5.0 6.0 5.0]
[ 3.0 5.0 7.0 0.8]]
我正在使用的当前代码如下:
row_idx = list(matrix_coo.row)
col_idx = list(matrix_coo.col)
data_idx = list(matrix_coo.data)
x = 0
while x < len(row_cost_idx):
for m in graph_array:
if m[1] == row_idx[x]:
if m[2] == col_idx[x]:
m[3] = data_idx[x]
x += 1
它的确为我提供了正确的输出,但是由于该数组有21596个项目,而矩阵有21596行,因此需要很长时间。
有更快的方法吗?
您的迭代是纯Python列表操作。 这一事实row_idx
最初是作为一的属性coo_matrix
不适用
可以用以下方法清除它:
什么是row_cost_idx
? 如果与row_idx
相同,我们可以做
for r,c,d in zip(matrix_coo.row, matrix_coo.col, matrix_coo.data):
for m in graph_array: # not list_graph?
if m[:2]==[r,c]:
m[3] = d
我认为迭代是相同的,但尚未对其进行测试。 我也不知道速度。
在matrix_coo
非零元素和graph_array
子列表上的两次迭代注定会很慢,这仅仅是因为您要进行很多次迭代。
如果graph_array
是一个numpy
array
,我们可以一次测试所有行,例如
mask = (graph_array[:, :2]==[r,c]).all(axis=1)
graph_array[mask,3] = d
其中对具有正确索引的graph_array
行, mask
将为1。 (同样,这未经测试)
为了提高速度,我将graph_array
和matrix_coo
都graph_array
为2d numpy(密集)数组,并查看是否可以通过一些数组操作解决问题。 从中得出的见解可能会帮助我替换matrix_coo
迭代。
========================
经过测试的代码
import numpy as np
from scipy import sparse
graph_array = np.array([[ 1.0, 1.0, 5.0 , 9.0],
[ 2.0, 5.0 , 6.0 , 5.0],
[ 3.0 , 5.0 , 7.0 , 6.0]])
r,c,d = [1,2,5], [5,8,7],[0.5,0.4,0.8]
matrix_coo = sparse.coo_matrix((d,(r,c)))
def org(graph_array, matrix_coo):
row_idx = list(matrix_coo.row)
col_idx = list(matrix_coo.col)
data_idx = list(matrix_coo.data)
x = 0
while x < len(row_idx):
for m in graph_array:
if m[1] == row_idx[x]:
if m[2] == col_idx[x]:
m[3] = data_idx[x]
x += 1
return graph_array
new_array = org(graph_array.copy(), matrix_coo)
print(graph_array)
print(new_array)
def alt(graph_array, matrix_coo):
for r,c,d in zip(matrix_coo.row, matrix_coo.col, matrix_coo.data):
for m in graph_array:
if (m[[1,2]]==[r,c]).all(): # array test
m[3] = d
return graph_array
new_array = alt(graph_array.copy(), matrix_coo)
print(new_array)
def altlist(graph_array, matrix_coo):
for r,c,d in zip(matrix_coo.row, matrix_coo.col, matrix_coo.data):
for m in graph_array:
if (m[1:3]==[r,c]): # list test
m[3] = d
return graph_array
new_array = altlist(graph_array.tolist(), matrix_coo)
print(new_array)
def altarr(graph_array, matrix_coo):
for r,c,d in zip(matrix_coo.row, matrix_coo.col, matrix_coo.data):
mask = (graph_array[:, 1:3]==[r,c]).all(axis=1)
graph_array[mask,3] = d
return graph_array
new_array = alt(graph_array.copy(), matrix_coo)
print(new_array)
跑
0909:~/mypy$ python3 stack3727173.py
[[ 1. 1. 5. 9.]
[ 2. 5. 6. 5.]
[ 3. 5. 7. 6.]]
[[ 1. 1. 5. 0.5]
[ 2. 5. 6. 5. ]
[ 3. 5. 7. 0.8]]
[[ 1. 1. 5. 0.5]
[ 2. 5. 6. 5. ]
[ 3. 5. 7. 0.8]]
[[1.0, 1.0, 5.0, 0.5], [2.0, 5.0, 6.0, 5.0], [3.0, 5.0, 7.0, 0.80000000000000004]]
[[ 1. 1. 5. 0.5]
[ 2. 5. 6. 5. ]
[ 3. 5. 7. 0.8]]
对于这个小例子,您的功能最快。 它也适用于列表和数组。 对于小型的物料清单操作,通常比数组操作更快。 因此,使用数组运算仅比较两个数字并没有改善。
复制graph_array
1000倍的altarr
版本比您的代码快10倍。 它正在最大范围内执行阵列操作。 我没有尝试增加matrix_coo
的大小。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.