在没有循环的数组中累加数字。(python)
所以我有一个(看起来)简单的问题,我现在通过for循环来解决这个问题 基本上,我希望在numpy矩阵中增加特定的单元格,但如果可能的话,我希望不使用for循环 要提供更多详细信息:我有在没有循环的数组中累加数字。(python),python,numpy,for-loop,optimization,vectorization,Python,Numpy,For Loop,Optimization,Vectorization,所以我有一个(看起来)简单的问题,我现在通过for循环来解决这个问题 基本上,我希望在numpy矩阵中增加特定的单元格,但如果可能的话,我希望不使用for循环 要提供更多详细信息:我有100x100numpy矩阵,x。我还有一个2x1000numpy矩阵PP只是将索引存储到X,因此,例如,P的每一列都有单元格的行-列索引,我想在X中增加该索引 我现在做的是: for p in range(P.shape[1]): X[P[0,p], P[1,p]] += 1 我的问题是,有没有一种不使用f
100x100
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循环的方法来实现这一点
谢谢 使用add
ufunc的方法:
或者,如果p
保证不会选择X
的同一单元格两次,则只需进行高级索引:
X[P[0], P[1]] += 1
使用add
ufunc的方法:
或者,如果p
保证不会选择X
的同一单元格两次,则只需进行高级索引:
X[P[0], P[1]] += 1
使用
线性指数
和bincount
-
lidx = np.ravel_multi_index(P, X.shape)
X += np.bincount(lidx, minlength=X.size).reshape(X.shape)
标杆管理
对于索引不重复的情况,中建议的基于的高级索引方法似乎非常有效
对于重复的情况,我们有np.add.at
和np.bincount
,性能数字似乎取决于索引数组相对于输入数组的大小
接近-
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:
案例2:
案例3:
使用
线性指数
和bincount
-
lidx = np.ravel_multi_index(P, X.shape)
X += np.bincount(lidx, minlength=X.size).reshape(X.shape)
标杆管理
对于索引不重复的情况,中建议的基于的高级索引方法似乎非常有效
对于重复的情况,我们有np.add.at
和np.bincount
,性能数字似乎取决于索引数组相对于输入数组的大小
接近-
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:
案例2:
案例3:
对于范围内的p(p.shape[1]):
可能?@Divakar是的,抱歉,更正了错误<代码>范围内的p(p.shape[1]):可能?@Divakar是的,抱歉,更正了错误!我花了一段时间才明白你为什么这么做。重复指数是一种痛苦。我花了一段时间才意识到你为什么这么做。重复索引是一种痛苦。P[0],P[1]
可以更一般地表示为(*P,)
。所以numpy.add.at(X,(*P,),1)
和X[(P,)]+=1
。这很好,因为它不会在维度数上进行硬编码。@Mad物理学家:或者只是tuple(P)
,但我选择P[0],P[1]
,因为我觉得这种情况更清楚。嗨,很可能有重复的索引。这是否意味着我应该使用第一个选项?第二个问题是,为什么第一个选项比for循环更好?谢谢@他们是用石墨笔写的。Pythonfor
循环对于速度不是很好。从功能上讲,循环与使用add.at
没有什么不同,但它的速度要慢得多,需要输入更多的文本。@Grapebyond:就是这样,假设您编写了类似的包装器和类似的C级代码,那么是的。P[0],P[1]
可以更一般地表示为(*P,)
。所以numpy.add.at(X,(*P,),1)
和X[(P,)]+=1
。这很好,因为它不会在维度数上进行硬编码。@Mad物理学家:或者只是tuple(P)
,但我选择P[0],P[1]
,因为我觉得这种情况更清楚。嗨,很可能有重复的索引。这是否意味着我应该使用第一个选项?第二个问题是,为什么第一个选项比for循环更好?谢谢@他们是用石墨笔写的。Pythonfor
循环对于速度不是很好。从功能上讲,循环与使用add.at
没有什么不同,但它的速度要慢得多,需要输入更多的文本。@TheGraphibeyond:就是这样,假设您编写了类似的包装器和类似的C级代码,那么是的。
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