重塑任意集合 numpy 数组

reshaping an arbitrary collection numpy arrays

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

为明确起见,这是我正在尝试做的具体示例。

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]])

速度是一个关键问题,因此 for 循环慢得令人无法接受。我一直无法弄清楚如何使用 np.reshape 或 np.concatenate 来执行此操作,但我知道必须有一些简单的单行 numpy 语法。

你可以使用 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]])

您可以使用 column_stack:

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

Internally 这使得三个数组成为 2D(如果可能,不制作副本),转置它们,然后连接它们。 concatenate 函数是一个内部 C 函数,因此它在速度方面可能是高效的。

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

  • 使用vstack并转置:

    p = numpy.vstack((x, y, z)).T
    
  • 使用concatenate and reshape

    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

我还包含了 中的方法,并在最后一个中尝试了行优先排序和列优先排序。在时间方面似乎大致有两组方法,120ms 类方法和 150ms 类方法,可能值得注意的是,行优先顺序 ('C') 是后一组,而列-主要订单 ('F') 是前一组中的一个。

我怀疑这些值不够可靠,无法区分这些方法。我鼓励您自己进行测试,看看哪个最快。

好的,感谢大家的热心解答。正如我所怀疑的那样,numpy 中有一行代码正是为了这个目的。 Transpose、vstack 和 column_stack 都是我所做工作的巨大速度改进。

有四种建议的解决方案,全部return正确的数组:

  • 连接 + 转置 (David Z)

  • vstack(大卫 Z)

  • 预分配 + 切片赋值 (David Z)

  • column_stack (ajcr)

下面的结论是:在所有情况下,concatenate + transpose 是最快的算法。

我对解决方案如何与 kN 进行了一些简单的探索,在 k ~ N 范围,以及 k << N 范围。不过,值得注意的是,即使对于非常大的 N,运行 时间也小于 1 秒,因此只有 MCMC 类型的应用程序才应该真正大惊小怪。的事情。

这是我的测试摘要运行:

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

  • k << N 范围内,我注意到 vstack连接+转置。在这种情况下,无论 kN.[=12 的值如何,它们 return 的时间都在 1-5% 以内=]

  • k << N 范围内,我注意到 column_stack预分配和切片赋值。在这种情况下,无论 kN 的值如何,它们 return 的时间都在 1-5% 之内。

  • k << N 范围内,vstack 比 [=65= 快 50-500% ]column_stack。这个分数速度差仅随着 N 缓慢增加,但随着 k 迅速增加。 N越大,随着k.

  • 的分数增长速度越快
  • k ~ N 机制中(与我的问题无关,但可能与其他问题相关),concatenate + transpose 是最快的, 预分配和切片赋值 落后 10-50%。

  • k ~ N范围内,column_stackvstack 速度大致相同,比 concatenate + transpose.

  • 慢 500-1000%

所以,正如我上面所说,结果是 concatenate + transpose 是所有机制中最快的:

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

然而,在与原始问题相关的机制中,vstack 方法具有相同的性能,并且语法规则更少:

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