将 2d NumPy 数组重塑为具有重复行的 3d
Reshaping 2d NumPy array into 3d with recurring rows
我有一个 NumPy 数组如下:
arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])
我正在寻找这样的安排:
[[[6,7,8,9,10],
[1,2,3,4,5]],
[[11,12,13,14,15],
[6,7,8,9,10]],
[[16,17,18,19,20],
[11,12,13,14,15]]]
所以本质上是一个 3D 数组,数组的每一行都有 2x5。
我试过的代码是:
x=np.zeros([3,2,5])
for i in range(len(arr)):
x[i]=arr[i:i+2,:][::-1]
但这会导致以下输出:
[[[ 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5.]]
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]]
[[[ 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5.]]
[[11. 12. 13. 14. 15.]
[ 6. 7. 8. 9. 10.]]
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]]
[[[ 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5.]]
[[11. 12. 13. 14. 15.]
[ 6. 7. 8. 9. 10.]]
[[16. 17. 18. 19. 20.]
[11. 12. 13. 14. 15.]]]
无需使用任何循环。切片就够了:
x = np.zeros([3,2,5], dtype=int)
x[:,0] = arr[-3:,:]
x[:,1] = arr[:3,:]
基本上,您将所有页面中的第 0 行分配给 arr
的最后 3 行,并将所有页面中的第 1 行分配给 arr
的前 3 行。[=13] =]
您可以使用一些 stride tricks 将数组构造为在输入数组上滑动 window 的多维数组:
import numpy as np
arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])
# compute the strides and shape of the output array
in_strides = arr.strides
out_strides = in_strides[:1] + in_strides
out_shape = (3, 2) + arr.shape[-1:] # keep the last dimension's size
strided = np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape)
out_arr = strided[:, ::-1, :].copy() # use a copy to stay safe
只要 out_shape[-1] <= arr.shape[1]
和 sum(out_shape[:2]) <= arr.shape[0] + 1
以上内容就可以安全运行。这些是使滑动 window 在原始数组中有意义的约束,您的实际用例自然应该遵守这些约束。
重要提示:
如果上述不等式不成立,那么滑动 window 将愉快地滑出数组的内存范围,您将静静地开始看到垃圾矩阵元素:
>>> out_strides = in_strides[:1] + in_strides
... out_shape = (3, 3, 5) # 3 + 3 == 6 > arr.shape[0] + 1 == 5
... np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape)
array([[[ 1, 2, 3, 4,
5],
[ 6, 7, 8, 9,
10],
[ 11, 12, 13, 14,
15]],
[[ 6, 7, 8, 9,
10],
[ 11, 12, 13, 14,
15],
[ 16, 17, 18, 19,
20]],
[[ 11, 12, 13, 14,
15],
[ 16, 17, 18, 19,
20],
[ 384, 193, 94379169559968, 0,
0]]])
- 如果你之后不会改变你的数组,并且只有这样,你可以省略上面最后的
.copy()
调用。这将为您提供一个与原始数组共享内存的跨步数组,但更重要的是,数组的行将彼此共享内存。这 不是 您通常想要的,但是如果您的实际数组非常大 and 您知道您可以安全地假设这些值不会独立变异,内存占用可能很重要。另一个需要考虑的方面是,对结果调用 .copy()
会给你一个连续的内存块,这可能对性能更好,具体取决于你打算对结果数组做什么。
我们可以利用 np.lib.stride_tricks.as_strided
based scikit-image's view_as_windows
to get sliding windows. .
from skimage.util.shape import view_as_windows
x = view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]
这只是输入数组的一个视图。因此,没有额外的内存开销和几乎免费的 运行 时间。如果你想要一个带有自己内存 space 的输出,请在此处附加 .copy()
,即 x.copy()
.
样本运行-
In [15]: from skimage.util.shape import view_as_windows
In [16]: view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]
Out[16]:
array([[[ 6, 7, 8, 9, 10],
[ 1, 2, 3, 4, 5]],
[[11, 12, 13, 14, 15],
[ 6, 7, 8, 9, 10]],
[[16, 17, 18, 19, 20],
[11, 12, 13, 14, 15]]])
我有一个 NumPy 数组如下:
arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])
我正在寻找这样的安排:
[[[6,7,8,9,10],
[1,2,3,4,5]],
[[11,12,13,14,15],
[6,7,8,9,10]],
[[16,17,18,19,20],
[11,12,13,14,15]]]
所以本质上是一个 3D 数组,数组的每一行都有 2x5。 我试过的代码是:
x=np.zeros([3,2,5])
for i in range(len(arr)):
x[i]=arr[i:i+2,:][::-1]
但这会导致以下输出:
[[[ 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5.]]
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]]
[[[ 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5.]]
[[11. 12. 13. 14. 15.]
[ 6. 7. 8. 9. 10.]]
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]]
[[[ 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5.]]
[[11. 12. 13. 14. 15.]
[ 6. 7. 8. 9. 10.]]
[[16. 17. 18. 19. 20.]
[11. 12. 13. 14. 15.]]]
无需使用任何循环。切片就够了:
x = np.zeros([3,2,5], dtype=int)
x[:,0] = arr[-3:,:]
x[:,1] = arr[:3,:]
基本上,您将所有页面中的第 0 行分配给 arr
的最后 3 行,并将所有页面中的第 1 行分配给 arr
的前 3 行。[=13] =]
您可以使用一些 stride tricks 将数组构造为在输入数组上滑动 window 的多维数组:
import numpy as np
arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])
# compute the strides and shape of the output array
in_strides = arr.strides
out_strides = in_strides[:1] + in_strides
out_shape = (3, 2) + arr.shape[-1:] # keep the last dimension's size
strided = np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape)
out_arr = strided[:, ::-1, :].copy() # use a copy to stay safe
只要 out_shape[-1] <= arr.shape[1]
和 sum(out_shape[:2]) <= arr.shape[0] + 1
以上内容就可以安全运行。这些是使滑动 window 在原始数组中有意义的约束,您的实际用例自然应该遵守这些约束。
重要提示:
如果上述不等式不成立,那么滑动 window 将愉快地滑出数组的内存范围,您将静静地开始看到垃圾矩阵元素:
>>> out_strides = in_strides[:1] + in_strides ... out_shape = (3, 3, 5) # 3 + 3 == 6 > arr.shape[0] + 1 == 5 ... np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape) array([[[ 1, 2, 3, 4, 5], [ 6, 7, 8, 9, 10], [ 11, 12, 13, 14, 15]], [[ 6, 7, 8, 9, 10], [ 11, 12, 13, 14, 15], [ 16, 17, 18, 19, 20]], [[ 11, 12, 13, 14, 15], [ 16, 17, 18, 19, 20], [ 384, 193, 94379169559968, 0, 0]]])
- 如果你之后不会改变你的数组,并且只有这样,你可以省略上面最后的
.copy()
调用。这将为您提供一个与原始数组共享内存的跨步数组,但更重要的是,数组的行将彼此共享内存。这 不是 您通常想要的,但是如果您的实际数组非常大 and 您知道您可以安全地假设这些值不会独立变异,内存占用可能很重要。另一个需要考虑的方面是,对结果调用.copy()
会给你一个连续的内存块,这可能对性能更好,具体取决于你打算对结果数组做什么。
我们可以利用 np.lib.stride_tricks.as_strided
based scikit-image's view_as_windows
to get sliding windows.
from skimage.util.shape import view_as_windows
x = view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]
这只是输入数组的一个视图。因此,没有额外的内存开销和几乎免费的 运行 时间。如果你想要一个带有自己内存 space 的输出,请在此处附加 .copy()
,即 x.copy()
.
样本运行-
In [15]: from skimage.util.shape import view_as_windows
In [16]: view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]
Out[16]:
array([[[ 6, 7, 8, 9, 10],
[ 1, 2, 3, 4, 5]],
[[11, 12, 13, 14, 15],
[ 6, 7, 8, 9, 10]],
[[16, 17, 18, 19, 20],
[11, 12, 13, 14, 15]]])