将具有多个维度的numpy数组转换为具有嵌套numpy数组的{2}数组

时间:2018-05-29 10:05:37

标签: numpy

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

因此,如果我有一个类似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, :, :, :]

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

2 个答案:

答案 0 :(得分:1)

我们可以重新整形并将常规数组中的元素分配到一个循环中的输出对象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

答案 1 :(得分:0)

感谢你提示米塔尔。这就是使用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))