我知道numpy.roll
可以沿一个或多个现有轴移动数组。我该如何在阵列x
上创建一个新轴,以使其沿着阵列shift
滚动其自身的视图或副本?
示例:
x = np.arange(10)
shift = np.array([2, 4])
#input
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
#output
array(
[[8, 6],
[9, 7],
[0, 8],
[1, 9],
[2, 0],
[3, 1],
[4, 2],
[5, 3],
[6, 4],
[7, 5]])
编辑:我正在寻找一种通用解决方案(理想情况下没有循环),该解决方案也可以应用于高维数组。另一个例子:
x = np.arange(20).reshape(2, 10)
shift = np.array([2, 4])
#input
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
#output
array(
[[[ 8, 6],
[ 9, 7],
[ 0, 8],
[ 1, 9],
[ 2, 0],
[ 3, 1],
[ 4, 2],
[ 5, 3],
[ 6, 4],
[ 7, 5]],
[[18, 16],
[19, 17],
[10, 18],
[11, 19],
[12, 10],
[13, 11],
[14, 12],
[15, 13],
[16, 14],
[17, 15]]])
答案 0 :(得分:2)
这是一个利用broadcasting
的矢量化解决方案,涵盖了通用n-dim
数组的情况-
np.take(x,(-shift + np.arange(x.shape[-1])[:,None]),axis=-1)
示例运行
1)x
为1D
-
In [114]: x = np.arange(10)
...: shift = np.array([2, 4])
In [115]: np.take(x,(-shift + np.arange(x.shape[-1])[:,None]),axis=-1)
Out[115]:
array([[8, 6],
[9, 7],
[0, 8],
[1, 9],
[2, 0],
[3, 1],
[4, 2],
[5, 3],
[6, 4],
[7, 5]])
2)x
为2D
-
In [116]: x = np.arange(20).reshape(2, 10)
...: shift = np.array([2, 4])
In [117]: np.take(x,(-shift + np.arange(x.shape[-1])[:,None]),axis=-1)
Out[117]:
array([[[ 8, 6],
[ 9, 7],
[ 0, 8],
[ 1, 9],
[ 2, 0],
[ 3, 1],
[ 4, 2],
[ 5, 3],
[ 6, 4],
[ 7, 5]],
[[18, 16],
[19, 17],
[10, 18],
[11, 19],
[12, 10],
[13, 11],
[14, 12],
[15, 13],
[16, 14],
[17, 15]]])
答案 1 :(得分:0)
我几乎不愿意提供这种替代方法,因为我认为@BenT的答案很简单且合乎逻辑
np.array([np.roll(x,sh) for sh in shift]).T
np.stack([np.roll(x,sh) for sh in shift], axis=1) # may be easier to generalize
但是我可以用x=np.arange(10)
做原始的as_strided
情况:
执行所有班次:
In [352]: arr = np.lib.stride_tricks.as_strided(np.hstack((x,x)),shape=(10,10), strides=(8,8))
In [353]: arr
Out[353]:
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
[2, 3, 4, 5, 6, 7, 8, 9, 0, 1],
[3, 4, 5, 6, 7, 8, 9, 0, 1, 2],
[4, 5, 6, 7, 8, 9, 0, 1, 2, 3],
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4],
[6, 7, 8, 9, 0, 1, 2, 3, 4, 5],
[7, 8, 9, 0, 1, 2, 3, 4, 5, 6],
[8, 9, 0, 1, 2, 3, 4, 5, 6, 7],
[9, 0, 1, 2, 3, 4, 5, 6, 7, 8]])
然后选择所需的对象:
In [358]: arr[::-1][shift-1]
Out[358]:
array([[8, 9, 0, 1, 2, 3, 4, 5, 6, 7],
[6, 7, 8, 9, 0, 1, 2, 3, 4, 5]])
我曾经尝试编写并测试过stack
版本,但是不得不尝试几件事才能使as_strided
正确。
我也希望将列表理解推广到更高的维度。
针对您的2d x
:
np.stack([np.roll(x,sh, axis=1) for sh in shift],2)