python多少维度_python – 几个维度的Numpy卷

理论上,使用@Ed Smith描述的scipy.ndimage.interpolation.shift应该可以工作,但是由于一个开放的bug(

https://github.com/scipy/scipy/issues/1323),它没有给出相当于np.roll的多次调用的结果.

更新:“多卷”功能在numpy版本1.12.0中添加到numpy.roll.这是一个二维示例,其中第一个轴滚动一个位置,第二个轴滚动三个位置:

In [7]: x = np.arange(20).reshape(4,5)

In [8]: x

Out[8]:

array([[ 0, 1, 2, 3, 4],

[ 5, 6, 7, 8, 9],

[10, 11, 12, 13, 14],

[15, 16, 17, 18, 19]])

In [9]: numpy.roll(x, [1, 3], axis=(0, 1))

Out[9]:

array([[17, 18, 19, 15, 16],

[ 2, 3, 4, 0, 1],

[ 7, 8, 9, 5, 6],

[12, 13, 14, 10, 11]])

这使得下面的代码已经过时了.我会把它留给后人.

下面的代码定义了一个我称之为multiroll的函数,可以执行您想要的操作.这是一个将其应用于形状为(500,500,500)的数组的示例:

In [64]: x = np.random.randn(500, 500, 500)

In [65]: shift = [10, 15, 20]

使用多次调用np.roll来生成预期结果:

In [66]: yroll3 = np.roll(np.roll(np.roll(x, shift[0], axis=0), shift[1], axis=1), shift[2], axis=2)

使用multiroll生成移位的数组:

In [67]: ymulti = multiroll(x, shift)

验证我们是否获得了预期结果:

In [68]: np.all(yroll3 == ymulti)

Out[68]: True

对于这个大小的数组,对np.roll进行三次调用几乎比调用multiroll要慢三倍:

In [69]: %timeit yroll3 = np.roll(np.roll(np.roll(x, shift[0], axis=0), shift[1], axis=1), shift[2], axis=2)

1 loops, best of 3: 1.34 s per loop

In [70]: %timeit ymulti = multiroll(x, shift)

1 loops, best of 3: 474 ms per loop

这是multiroll的定义:

from itertools import product

import numpy as np

def multiroll(x, shift, axis=None):

"""Roll an array along each axis.

Parameters

----------

x : array_like

Array to be rolled.

shift : sequence of int

Number of indices by which to shift each axis.

axis : sequence of int, optional

The axes to be rolled. If not given, all axes is assumed, and

len(shift) must equal the number of dimensions of x.

Returns

-------

y : numpy array, with the same type and size as x

The rolled array.

Notes

-----

The length of x along each axis must be positive. The function

does not handle arrays that have axes with length 0.

See Also

--------

numpy.roll

Example

-------

Here's a two-dimensional array:

>>> x = np.arange(20).reshape(4,5)

>>> x

array([[ 0, 1, 2, 3, 4],

[ 5, 6, 7, 8, 9],

[10, 11, 12, 13, 14],

[15, 16, 17, 18, 19]])

Roll the first axis one step and the second axis three steps:

>>> multiroll(x, [1, 3])

array([[17, 18, 19, 15, 16],

[ 2, 3, 4, 0, 1],

[ 7, 8, 9, 5, 6],

[12, 13, 14, 10, 11]])

That's equivalent to:

>>> np.roll(np.roll(x, 1, axis=0), 3, axis=1)

array([[17, 18, 19, 15, 16],

[ 2, 3, 4, 0, 1],

[ 7, 8, 9, 5, 6],

[12, 13, 14, 10, 11]])

Not all the axes must be rolled. The following uses

the `axis` argument to roll just the second axis:

>>> multiroll(x, [2], axis=[1])

array([[ 3, 4, 0, 1, 2],

[ 8, 9, 5, 6, 7],

[13, 14, 10, 11, 12],

[18, 19, 15, 16, 17]])

which is equivalent to:

>>> np.roll(x, 2, axis=1)

array([[ 3, 4, 0, 1, 2],

[ 8, 9, 5, 6, 7],

[13, 14, 10, 11, 12],

[18, 19, 15, 16, 17]])

"""

x = np.asarray(x)

if axis is None:

if len(shift) != x.ndim:

raise ValueError("The array has %d axes, but len(shift) is only "

"%d. When 'axis' is not given, a shift must be "

"provided for all axes." % (x.ndim, len(shift)))

axis = range(x.ndim)

else:

# axis does not have to contain all the axes. Here we append the

# missing axes to axis, and for each missing axis, append 0 to shift.

missing_axes = set(range(x.ndim)) - set(axis)

num_missing = len(missing_axes)

axis = tuple(axis) + tuple(missing_axes)

shift = tuple(shift) + (0,)*num_missing

# Use mod to convert all shifts to be values between 0 and the length

# of the corresponding axis.

shift = [s % x.shape[ax] for s, ax in zip(shift, axis)]

# Reorder the values in shift to correspond to axes 0, 1, ..., x.ndim-1.

shift = np.take(shift, np.argsort(axis))

# Create the output array, and copy the shifted blocks from x to y.

y = np.empty_like(x)

src_slices = [(slice(n-shft, n), slice(0, n-shft))

for shft, n in zip(shift, x.shape)]

dst_slices = [(slice(0, shft), slice(shft, n))

for shft, n in zip(shift, x.shape)]

src_blks = product(*src_slices)

dst_blks = product(*dst_slices)

for src_blk, dst_blk in zip(src_blks, dst_blks):

y[dst_blk] = x[src_blk]

return y

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值