我正在numpy(Python 2.7)中从1d数组构建2d数组。我正在寻找最有效的方法来做到这一点。到目前为止,我提出了:
a=np.ones(100000)
# SUBSCRIPTING
n_dim=3
x=0
for i in xrange(0,1000):
x=np.zeros(shape=(100000,n_dim))
for j in xrange(0,n_dim):
x[:,j]=a*j
# ~1.574 s/1000 loops - joinind 3 1d arrays
# ~9.162 s/1000 loops - joinind 10 1d arrays
# STACKING
for i in xrange(0,1000):
x=a*0.
for j in xrange(1,n_dim):
x=np.vstack((x,a*j))
x=x.T
# ~1.786 s/1000 loops - joinind 3 1d arrays
# ~16.603 s/1000 loops - joinind 10 1d arrays
第一种方法(下标)是我提出的最快的方法,第二种方法(堆叠)的性能提升随着我加入的1d数组的数量而增长。由于我需要重复这一步骤,我想知道是否有更快的东西?如果它提供显着的性能提升,我愿意采用明显失去的解决方案。
也许我可以尝试以限制堆叠操作次数的方式堆叠阵列(例如,连接4个1d阵列的情况:第一个堆栈阵列1和2,然后是阵列3和4,最后是结果阵列)。
我的问题是从1d数组有效地构建2d数组。我在这里使用的数组中的值是虚拟的。在实际应用中,我加入的1d数组中的大多数值可能会有所不同。
答案 0 :(得分:2)
因为numpy存储(默认情况下)row-major order中的数组,所以按行设置值会更有效。因此,我会使用:
x=np.zeros(shape=(n_dim, 100000))
for j in range(0,n_dim):
x[j,:]=a*j
或者,您可以将x
定义为列专业,然后,这与上一代码一样快:
x=np.zeros(shape=(100000,n_dim), order='F')
for j in range(0,n_dim):
x[:,j]=a*j
您还可以使用numpy外部产品创建x
:
v = np.arange(n_dim)
x = np.outer(v, a)
答案 1 :(得分:1)
这是使用vstack
的糟糕方式;您反复调用它,为每个x
j
x=a*0.
for j in xrange(1,n_dim):
x=np.vstack((x,a*j))
x=x.T
正确的方法是构建数组列表,并且只使用vstack
一次。
xlist=[]
for j in xrange(1,n_dim):
xlist.append(a*j)
x = np.array(xlist).T
在此上下文中,append
的工作方式与vstack
一样,并且可能更快。还有column_stack
功能。关键的区别在于我正在利用快速列表追加,以及array
(和vstack
)在其参数列表中包含多个项目的能力。
如果您可以将循环编写为列表理解
,那就更好了x = np.array([a*j for j in xrange(1,n_dim)])
在预分配数组中插入通常是最快的选择。但是你应该熟悉这种从列表构建的方法。
基本np.array
表达式
np.array([[1,2,3],[4,5,6]])
就是这样,从1d数组列表构建2d(或者在这种情况下列表)。
np.array([a*0,a*1,a*2])
jakub
注意到np.array
很慢。对于n_dim=10
:
In [257]: timeit x=np.array([(a*j) for j in range(n_dim)]).T
1 loops, best of 3: 228 ms per loop
In [258]: timeit x=np.array([(a*j).tolist() for j in range(n_dim)]).T
1 loops, best of 3: 228 ms per loop
显然np.array
正在将输入数组转换为列表,然后从嵌套列表(或类似的东西)中进行常规构造。
In [259]: timeit x=np.vstack([(a*j) for j in range(n_dim)]).T
10 loops, best of 3: 24.9 ms per loop
数组列表上的 vstack
要快得多。比迭代vstack
(我预期的)更快。与Ramon's
行插入(并插入order='F'
)
In [272]: %%timeit
x=np.zeros((n_dim,a.shape[0]))
for j in range(n_dim):
x[j,:]=a*j
.....: x=x.T
.....:
10 loops, best of 3: 23.3 ms per loop
虽然编译concatenate
(由vstack
使用),但我怀疑它与迭代插入类似。源C代码中常见的是创建一个空的目标数组,然后用适当的值填充它。