[英]Efficient way to construct this array in numpy?
I need to construct an N x M x N
array A
such that A[i, j, k] == (0 if i != k else x[j])
. 我需要构造一个
N x M x N
阵列A
,使得A[i, j, k] == (0 if i != k else x[j])
。 I could write: 我可以写:
A = np.zeros((N, M, N))
for i in range(N):
for j in range(M):
A[i,j,i] = x[j]
Or, alternatively: 或者,或者:
A = np.zeros((N, M, N))
for i in range(N):
A[i,:,i] = x
But both are most likely too slow for my purposes. 但两者都很可能对我的目的来说太慢了。 Is there a faster way?
有更快的方法吗?
Approach #1 方法#1
Using broadcasting
to create all those linear indices where x
's are to be assigned and then simply assign into its flattened view, like so - 使用
broadcasting
来创建所有那些要分配x
的线性索引,然后简单地分配到它的展平视图中,就像这样 -
# Initialize
Aout = np.zeros((N, M, N))
# Comput all linear indices
idx = (np.arange(N)*(N*M+1))[:,None] + N*np.arange(M)
# In a flattened view with `.ravel()` assign from x
Aout.ravel()[idx] = x
Approach #2 方法#2
Using views based element access supported by np.lib.stride_tricks.as_strided
- 使用
np.lib.stride_tricks.as_strided
支持的基于视图的元素访问 -
Aout = np.zeros((N, M, N))
s0,s1,s2 = Aout.strides
Aoutview = np.lib.stride_tricks.as_strided(Aout,shape=(N,M),strides=(s0+s2,s1))
Aoutview[:] = x
Approach #3 方法#3
Another approach would be to use integer array indexing
along the first and third axes, closely simulating the second approach from the question, but in a vectorized manner - 另一种方法是沿第一和第三轴使用
integer array indexing
,从问题中模拟第二种方法,但是以矢量化方式 -
Aout = np.zeros((N, M, N))
Aout[np.arange(N),:,np.arange(N)] = x
Runtime test 运行时测试
Approaches - 方法 -
def app0(x,A):
for i in range(N):
for j in range(M):
A[i,j,i] = x[j]
return A
def app1(x,A):
for i in range(N):
A[i,:,i] = x
return A
def app2(x,Aout):
idx = (np.arange(N)*(N*M+1))[:,None] + N*np.arange(M)
Aout.ravel()[idx] = x
return Aout
def app3(x,Aout):
s0,s1,s2 = Aout.strides
Aoutview = np.lib.index_tricks.as_strided(Aout,shape=(N,M),strides=(s0+s2,s1))
Aoutview[:] = x
return Aout
def app4(x,Aout):
r = np.arange(N)
Aout[r,:,r] = x
return Aout
Verification - 验证 -
In [125]: # Params
...: N, M = 100,100
...: x = np.random.rand(M)
...:
...: # Make copies of arrays to be assigned into
...: A0 = np.zeros((N, M, N))
...: A1 = np.zeros((N, M, N))
...: A2 = np.zeros((N, M, N))
...: A3 = np.zeros((N, M, N))
...: A4 = np.zeros((N, M, N))
...:
In [126]: print np.allclose(app0(x,A0), app1(x,A1))
...: print np.allclose(app0(x,A0), app2(x,A2))
...: print np.allclose(app0(x,A0), app3(x,A3))
...: print np.allclose(app0(x,A0), app4(x,A4))
...:
True
True
True
True
Timings - 计时 -
In [127]: # Make copies of arrays to be assigned into
...: A0 = np.zeros((N, M, N))
...: A1 = np.zeros((N, M, N))
...: A2 = np.zeros((N, M, N))
...: A3 = np.zeros((N, M, N))
...: A4 = np.zeros((N, M, N))
In [128]: %timeit app0(x,A0)
...: %timeit app1(x,A1)
...: %timeit app2(x,A2)
...: %timeit app3(x,A3)
...: %timeit app4(x,A4)
...:
1000 loops, best of 3: 1.49 ms per loop
10000 loops, best of 3: 53.6 µs per loop
10000 loops, best of 3: 150 µs per loop
10000 loops, best of 3: 28.6 µs per loop
10000 loops, best of 3: 25.2 µs per loop
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.