使3-d numpy数组的每个第n个切片连续

时间:2019-02-15 17:53:21

标签: python arrays python-3.x numpy

声明

假设我们有一些3维的numpy数组A,其形状为(X, Y, Z)。我想创建一个新数组B,它也将具有形状(X, Y, Z)

我们希望:n的第n个切片(B)沿第零个轴对应于::m的第m个切片(A)沿第零轴。

我们还希望n:2*n的切片B对应于m+1的每个第1::m个切片(A)。对于数组的其余部分,依此类推。

使用向量化numpy计算来实现此目标的最佳方法是什么?

示例

通过一个示例可以最好地理解上述陈述。因此,让我们开始设置一些示例数组A

import numpy as np

# Create array A with shape (15, 3, 3)
n = 3; m = 5
a = np.array([i * np.eye(3) for i in range(1, 1+m)])
A = np.tile(a, (n, 1, 1))

如果我们看一下A的第零个切片,就会发现:

print(A[0])
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
print(A[1])
[[2. 0. 0.]
 [0. 2. 0.]
 [0. 0. 2.]]

...

print(A[4])
[[5. 0. 0.]
 [0. 5. 0.]
 [0. 0. 5.]]
print(A[5])
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

以此类推。

A 中的值并不重要,但应有助于说明原始语句。

我想知道我们是否只能使用numpy函数创建矩阵B。数组B应该具有切片:

print(B[0])
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
print(B[1])
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
print(B[2])
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
print(B[3])
[[2. 0. 0.]
 [0. 2. 0.]
 [0. 0. 2.]]

以此类推。

有什么方法可以通过纯粹的numpy解决方案从B生成A

我尝试过的

以下内容根据需要提供B,但是随着m变大,它变得很乏味:

# vstack solution
B = np.vstack((A[::m], A[1::m], A[2::m], A[3::m], A[4::m]))

使用列表推导也可以,但是我想避免使用循环:

# List comprehension solution
B = np.vstack([A[i::m] for i in range(m)])

3 个答案:

答案 0 :(得分:1)

我认为这可以满足您的要求

import numpy as np

# Create array A with shape (15, 3, 3)
a = np.array([i * np.eye(3) for i in range(1, 6)])
A = np.tile(a, (3, 1, 1))

B = np.swapaxes(A.reshape(3, 5, 3, 3), 0, 1)
B = B.reshape(-1, 3, 3)
print(B)
# [[[1. 0. 0.]
#   [0. 1. 0.]
#   [0. 0. 1.]]
#
#  [[1. 0. 0.]
#   [0. 1. 0.]
#   [0. 0. 1.]]
#
#  [[1. 0. 0.]
#   [0. 1. 0.]
#   [0. 0. 1.]]
#
#  [[2. 0. 0.]
#   [0. 2. 0.]
#   [0. 0. 2.]]
# ...

答案 1 :(得分:1)

据我了解,也许您可​​以只使用numpy.sort

B = np.sort(A, axis = 0)

答案 2 :(得分:1)

设置

n = 3; m = 5
a = np.array([i * np.eye(n) for i in range(1, 1+m)])

代替tile,沿轴0使用np.repeat,并使用Fortran样式排序进行整形。

np.repeat(a, n, 0).reshape(m*n, n, n, order='F')

array([[[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]],

       [[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]],

       [[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]],

       [[2., 0., 0.],
        [0., 2., 0.],
        [0., 0., 2.]],    
       ...    
       [[5., 0., 0.],
        [0., 5., 0.],
        [0., 0., 5.]]])

验证

# your approach
A = np.tile(a, (n, 1, 1))
B = np.vstack((A[::m], A[1::m], A[2::m], A[3::m], A[4::m]))

# my approach
usr_B = np.repeat(a, n, 0).reshape(m*n, n, n, order='F')

>>> np.array_equal(B, usr_B)
True

时间

%%timeit
A = np.tile(a, (n, 1, 1))
B = np.vstack((A[::m], A[1::m], A[2::m], A[3::m], A[4::m]))
19 µs ± 57.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%%timeit
A = np.tile(a, (3, 1, 1))
B = np.swapaxes(A.reshape(3, 5, 3, 3), 0, 1)
B = B.reshape(-1, 3, 3)
11 µs ± 74.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit np.repeat(a, n, 0).reshape(m*n, n, n, order='F')
2.68 µs ± 21.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)