假设我有2个矩阵M和N(两个都有> 1列)。我还有一个索引矩阵I,有2列 - 1表示M,1表示N.N的索引是唯一的,但M的索引可能出现不止一次。我想要执行的操作是,
for i,j in w:
M[i] += N[j]
除了for循环之外,还有更有效的方法吗?
答案 0 :(得分:12)
为了完整性,在numpy> = 1.8中,您还可以使用np.add
' s at
方法:
In [8]: m, n = np.random.rand(2, 10)
In [9]: m_idx, n_idx = np.random.randint(10, size=(2, 20))
In [10]: m0 = m.copy()
In [11]: np.add.at(m, m_idx, n[n_idx])
In [13]: m0 += np.bincount(m_idx, weights=n[n_idx], minlength=len(m))
In [14]: np.allclose(m, m0)
Out[14]: True
In [15]: %timeit np.add.at(m, m_idx, n[n_idx])
100000 loops, best of 3: 9.49 us per loop
In [16]: %timeit np.bincount(m_idx, weights=n[n_idx], minlength=len(m))
1000000 loops, best of 3: 1.54 us per loop
除了明显的性能劣势之外,它还有一些优势:
np.bincount
将其权重转换为双精度浮点数,.at
将与数组的本机类型一起运行。这使得它成为处理例如最简单的选择。数字复杂。np.bincount
只会将权重加在一起,您对所有ufunc都有一个at
方法,因此您可以重复multiply
,或logical_and
,或者您想要的任何内容。< / LI>
醇>
但是对于您的用例,np.bincount
可能是要走的路。
答案 1 :(得分:3)
同时使用m_ind, n_ind = w.T
,只需执行M += np.bincount(m_ind, weights=N[n_ind], minlength=len(M))
答案 2 :(得分:1)
为清楚起见,我们来定义
>>> m_ind, n_ind = w.T
然后是for
循环
for i, j in zip(m_ind, n_ind):
M[i] += N[j]
更新条目M[np.unique(m_ind)]
。写入的值为N[n_ind]
,必须按m_ind
分组。 (除了n_ind
之外还有m_ind
这个问题实际上与问题相关;您可以设置N = N[n_ind]
。)恰好有一个SciPy类正是这样做的:{ {3}}
示例数据:
>>> m_ind, n_ind = array([[0, 0, 1, 1], [2, 3, 0, 1]])
>>> M = np.arange(2, 6)
>>> N = np.logspace(2, 5, 4)
for
循环的结果是M
变为[110002 1103 4 5]
。我们得到与csr_matrix
相同的结果,如下所示。正如我之前所说,n_ind
是不相关的,所以我们先摆脱它。
>>> N = N[n_ind]
>>> from scipy.sparse import csr_matrix
>>> update = csr_matrix((N, m_ind, [0, len(N)])).toarray()
CSR构造函数在所需索引处构建一个具有所需值的矩阵;其参数的第三部分是压缩列索引,这意味着值N[0:len(N)]
具有索引m_ind[0:len(N)]
。重复项总结:
>>> update
array([[ 110000., 1100.]])
这具有(1, len(np.unique(m_ind)))
形状,可以直接添加:
>>> M[np.unique(m_ind)] += update.ravel()
>>> M
array([110002, 1103, 4, 5])