重塑任意集合numpy数组



我有一个相对较小的k长度N的numpy数组,其中k为10阶,N非常大,为10^7阶。我正试图创建一个单一的二维Nxk数组,以特定的方式捆绑这些数据。

为了明确起见,这里有一个我试图做的具体例子

x = np.array([0,0,0,0])
y = np.array([1,1,1,1])
z = np.array([2,2,2,2])

最后我想要的数组是:

p = np.array([[0,1,2], [0,1,2], [0,1,2], [0,1,2]])

速度是一个关键问题,因此循环的速度慢得令人无法接受。我还不知道如何使用np.reshape或np.contenate来实现这一点,但我知道必须有一些简单的、单行的numpy语法。

您可以使用column_stack:

>>> np.column_stack([x, y, z])
array([[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]])

在内部,这使三个数组成为2D(如果可能的话,不进行复制),将它们转置,然后连接thm。concatenate函数是一个内部C函数,因此它可能是高效的速度函数。

以下是您可以尝试的几种方法:

  • 使用vstack和转置:

    p = numpy.vstack((x, y, z)).T
    
  • 使用concatenatereshape

    p = numpy.concatenate((x, y, z)).reshape((3, len(x))).T
    
  • 分配新阵列并使用put

    p = numpy.empty((len(x), 3))
    for i, a in enumerate((x, y, z)):
    p[:,i] = a
    

连同在iPython中计算的len(x) == len(y) == len(z) == 1e7:的计时结果

In [57]: %timeit p = numpy.vstack((x, y, z)).T
10 loops, best of 3: 117 ms per loop
In [58]: %timeit p = numpy.concatenate((x, y, z)).reshape((3, len(x))).T
10 loops, best of 3: 120 ms per loop
In [60]: %timeit p = numpy.column_stack((x, y, z))
10 loops, best of 3: 159 ms per loop
In [66]: %%timeit
....: p = numpy.empty((len(x), 3), order='C')
....: for i, a in enumerate((x, y, z)):
....:   p[:,i] = a
....: 
10 loops, best of 3: 147 ms per loop
In [67]: %%timeit
....: p = numpy.empty((len(x), 3), order='F')
....: for i, a in enumerate((x, y, z)):
....:   p[:,i] = a
....: 
10 loops, best of 3: 119 ms per loop

我还包括了ajcr答案中的方法,并在最后一个中尝试了行主和列主排序。就时间而言,似乎大约有两组方法,类似120ms的方法和类似150ms的方法,值得注意的是,行主序('C')是后一组方法之一,而列主序('F')是前一组方法。

我怀疑这些值不够可靠,无法区分不同的方法。我鼓励你自己做测试,看看哪一个最快。

您可以使用np.concatenate

In [117]: np.concatenate(([x], [y], [z]), axis=0).T
Out[117]:
array([[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]])

此外,您可以迭代地附加数组,然后进行转置。

注意:这有3个循环。

In [113]: arr = np.empty((0,4), int)
In [114]: for el in [x, y, z]:
.....:     arr = np.append(arr, [el], axis=0)
.....:
In [115]: arr
Out[115]:
array([[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2]])
In [116]: arr.T
Out[116]:
array([[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]])

好的,感谢大家的帮助。正如我所怀疑的,numpy中有一句话正是为了这个目的。Transpose、vstack和column_stack都是对我所做工作的巨大速度改进。

有四种建议的解决方案,所有这些方案都返回正确的阵列:

  • 连接+转置(David Z)

  • vstack(David Z)

  • 预分配+按片分配(David Z)

  • column_stack(ajcr)

下面的结果是:在所有机制中,连接+转置是最快的算法

我对解决方案如何与kN同时缩放进行了一些简单的探索,在k+Nregion和k<lt;N制度。不过,值得注意的是,即使对于非常大的N,运行时间也小于1秒,因此只有对于MCMC类型的应用程序,才应该对这类事情大惊小怪。

以下是我运行的测试摘要:

  • 首先,我可以定量地证实David Z进行的速度测试。此外,在他探索的制度中,我发现他发现的差异是稳健的,而不是简单的波动。请参见下文。

  • k<lt;N机制,我注意到vstack连接+转置之间没有明显的差异。在这种情况下,无论kN的值如何,它们返回的时间都在1-5%以内。

  • k<lt;N制度,我注意到column_stack预分配&按片分配。在这种情况下,无论kN的值如何,它们返回的时间都在1-5%以内。

  • k<lt;vstackcolumn_stack快50-500%。该分数速度差仅随N缓慢增加,但随k快速增加。N越大,分数随k的增加速度越快。

  • k~N机制中(与我的问题无关,但可能与其他问题有关),连接+转置是最快的,其中预分配&分片分配落后10-50%。

  • k~N机制中,column_stackvstack的速度大致相同,比连接+转置慢500-1000%。

所以,正如我上面所说,结果是连接+转置是所有机制中最快的:

p = np.concatenate((x, y, z)).reshape((3, len(x))).T

然而,在与原始问题相关的机制中,vstack方法具有等效的性能,并且对语法来说不太复杂:

p = numpy.vstack((x, y, z)).T

最新更新