所以我有一个(看似)简单的问题,我现在正在通过for循环做这个问题。
基本上,我想在numpy矩阵中增加特定单元格,但是如果可能的话,我想在没有for循环的情况下进行。
提供更多详细信息:我有100 x 100
numpy矩阵X
。我还有一个2x1000
numpy矩阵P
。 P
只会将索引存储到X
中,因此,例如,每个P
列都有单元格的行列索引,我希望在X
中递增。
我现在做的是:
for p in range(P.shape[1]):
X[P[0,p], P[1,p]] += 1
我的问题是,有没有办法在没有for循环的情况下做到这一点?
谢谢!
答案 0 :(得分:3)
使用add
ufunc的at
方法advanced indexing:
numpy.add.at(X, (P[0], P[1]), 1)
如果P
保证永远不会选择X
两次相同的单元格,那么或只是高级索引:
X[P[0], P[1]] += 1
答案 1 :(得分:2)
使用linear-indices
和bincount
-
lidx = np.ravel_multi_index(P, X.shape)
X += np.bincount(lidx, minlength=X.size).reshape(X.shape)
对于不重复索引的情况,@user2357112's post
中建议的基于advanced indexing
的方法似乎非常有效。
对于重复的情况,我们有np.add.at
和np.bincount
,性能数字似乎取决于index数组相对于输入数组大小的大小。
方法 -
def app0(X,P): # @user2357112's soln1
np.add.at(X, (P[0], P[1]), 1)
def app1(X, P): # Proposed in this ppst
lidx = np.ravel_multi_index(P, X.shape)
X += np.bincount(lidx, minlength=X.size).reshape(X.shape)
这里有几个时间测试表明 -
案例#1:
In [141]: X = np.random.randint(0,9,(100,100))
...: P = np.random.randint(0,100,(2,1000))
...:
In [142]: %timeit app0(X, P)
...: %timeit app1(X, P)
...:
10000 loops, best of 3: 68.9 µs per loop
100000 loops, best of 3: 15.1 µs per loop
案例#2:
In [143]: X = np.random.randint(0,9,(1000,1000))
...: P = np.random.randint(0,1000,(2,10000))
...:
In [144]: %timeit app0(X, P)
...: %timeit app1(X, P)
...:
1000 loops, best of 3: 687 µs per loop
1000 loops, best of 3: 1.48 ms per loop
案例#3:
In [145]: X = np.random.randint(0,9,(1000,1000))
...: P = np.random.randint(0,1000,(2,100000))
...:
In [146]: %timeit app0(X, P)
...: %timeit app1(X, P)
...:
100 loops, best of 3: 11.3 ms per loop
100 loops, best of 3: 2.51 ms per loop