【问题标题】:Convert numpy array with many dimensions into 2D array with nested numpy arrays将具有多个维度的 numpy 数组转换为具有嵌套 numpy 数组的二维数组
【发布时间】:2018-05-29 10:05:37
【问题描述】:

我想将一个多维(超过 2 个)的数组转换为一个二维数组,其中其他维度将转换为嵌套的独立数组。

所以如果我有一个像numpy.arange(3 * 4 * 5 * 5 * 5).reshape((3, 4, 5, 5, 5)) 这样的数组,我想将它转换为一个形状为(3, 4) 的数组,其中每个元素都是一个形状为(5, 5, 5) 的数组。外部数组的 dtype 为 object

例如,对于np.arange(8).reshape((1, 1, 2, 2, 2)),输出将等同于:

a = np.ndarray(shape=(1,1), dtype=object)
a[0, 0] = np.arange(8).reshape((1, 1, 2, 2, 2))[0, 0, :, :, :]

我怎样才能有效地做到这一点?

【问题讨论】:

  • 能否提供一个示例代码来展示您已经尝试过的内容?
  • 你能用np.arange(8).reshape((1, 1, 2, 2, 2)) 来显示预期的输出吗?你的例子太大了。
  • 添加了预期的输出示例。
  • 一个类似的 SO 问题,使用frompyfunc, Force numpy to create array of objects 给出了一个聪明(虽然速度较慢)的答案

标签: numpy


【解决方案1】:

我们可以在单个循环中重塑 regular 数组中的元素并将其分配到输出对象 dtype 数组中,这似乎比两个循环快一点,就像这样 -

def reshape_approach(a):
    m,n = a.shape[:2]
    a.shape = (m*n,) + a.shape[2:]
    out = np.empty((m*n),dtype=object)
    for i in range(m*n):
        out[i] = a[i]
    out.shape = (m,n)
    a.shape = (m,n) + a.shape[1:]
    return out

运行时测试

其他方法-

# @Scotty1-'s soln
def simply_assign(a):
    m,n = a.shape[:2]
    out = np.empty((m,n),dtype=object)
    for i in range(m):
        for j in range(n):
            out[i,j] = a[i,j]
    return out

时间安排 -

In [154]: m,n = 300,400
     ...: a = np.arange(m * n * 5 * 5 * 5).reshape((m,n, 5, 5, 5))

In [155]: %timeit simply_assign(a)
10 loops, best of 3: 39.4 ms per loop

In [156]: %timeit reshape_approach(a)
10 loops, best of 3: 32.9 ms per loop

使用7D 数据-

In [160]: m,n,p,q = 30,40,30,40
     ...: a = np.arange(m * n *p * q * 5 * 5 * 5).reshape((m,n,p,q, 5, 5, 5))

In [161]: %timeit simply_assign(a)
1000 loops, best of 3: 421 µs per loop

In [162]: %timeit reshape_approach(a)
1000 loops, best of 3: 316 µs per loop

【讨论】:

  • 很好的解决方案。但恕我直言,对于一项简单的任务来说太复杂了,如果效率不是生存的必要条件。可能更快的是做x.reshape(-1),然后使用步幅来完全避免循环。稍后我会对此进行研究。
  • @Scotty1- OP 要求性能,所以我不明白为什么几个额外的步骤会受到伤害:)
  • reshape 循环可以替换为out[:] = list(a),虽然时间基本相同。
  • @hpaulj 是的,试过了,但是明显慢了。
  • @Mitar 分配给形状是什么意思?
【解决方案2】:

感谢您的提示米塔尔。这就是使用 dtype=np.object 数组时的样子:

outer_array = np.empty((x.shape[0], x.shape[1]), dtype=np.object)
for i in range(x.shape[0]):
    for j in range(x.shape[1]):
        outer_array[i, j] = x[i, j]

循环可能不是最有效的方法,但是对于这个任务没有矢量化操作。

(使用更多的整形,这应该比 Divakar 的解决方案更快:;)) ---> 不,Divakar 更快.... 不错的解决方案 Divakar!

def advanced_reshape_solution(x):
    m, n = x.shape[:2]
    sub_arr_size = np.prod(x.shape[2:])
    out_array = np.empty((m * n), dtype=object)
    x_flat_view = x.reshape(-1)
    for i in range(m*n):
        out_array[i] = x_flat_view[i * sub_arr_size:(i + 1) * sub_arr_size].reshape(x.shape[2:])
    return out_array.reshape((m, n))

【讨论】:

  • 您可以将 numpy 数组作为对象存储在具有 dtype 对象的数组中。
  • 是这样吗?然后给我一秒钟来更新我的答案。
  • 这行得通。但仅限于 5 维数组。如何获得任意维数的子数组?
  • @Mitar 更新了我的解决方案。
  • 哦,这看起来比预期的要简单。 :-)
猜你喜欢
  • 1970-01-01
  • 2023-02-03
  • 2018-11-30
  • 2019-01-09
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
  • 2012-11-24
相关资源
最近更新 更多