繁体   English   中英

Numpy-从1D数组高效构建2D数组

[英]Numpy - efficiently building 2d array from 1d arrays

我正在从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

第一种方法(下标)是我想出的最快方法,而第二种方法(堆栈)的性能增益随着我加入的一维数组的数量而增长。 当我需要重复很多步骤时,我想知道是否有更快的方法? 我愿意采用一种解决方案,如果该解决方案可以显着提高性能,那么它会变得不清楚。

也许我可以尝试以限制堆栈操作数量的方式来堆栈数组(例如,连接4个1d数组的情况:首先堆栈数组1和2,然后是数组3和4,最后是结果数组)。

我的问题是关于从1d数组有效地构建2d数组。 我在这里使用的数组中的值是虚拟的。 在实际应用中,我加入的1d数组中的大多数值可能会有所不同。

由于numpy(默认情况下)按行优先顺序存储数组,因此按行设置值更有效。 因此,我将使用:

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)

这是使用vstack糟糕方法; 您反复调用它,为每个j创建一个新的x

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

在这种情况下, appendvstack一样好,并且可能更快。 还有一个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]])

就是这样,从一维数组列表(或本例中的列表)构建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代码中,通常创建一个空的目标数组,然后用适当的值填充它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM