Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 剪切numpy数组_Python_Optimization_Numpy_Premature Optimization - Fatal编程技术网

Python 剪切numpy数组

Python 剪切numpy数组,python,optimization,numpy,premature-optimization,Python,Optimization,Numpy,Premature Optimization,我想“剪切”一个numpy数组。我不确定我是否正确使用了“剪切”一词;我所说的剪切是指: 将第一列移动0位 将第二列移动1位 将第三列移动2位 等等 所以这个数组: array([[11, 12, 13], [17, 18, 19], [35, 36, 37]]) array([[11, 36, 19], [17, 12, 37], [35, 18, 13]]) array([[11, 0, 0], [17, 12,

我想“剪切”一个numpy数组。我不确定我是否正确使用了“剪切”一词;我所说的剪切是指:

将第一列移动0位
将第二列移动1位
将第三列移动2位
等等

所以这个数组:

array([[11, 12, 13],
       [17, 18, 19],
       [35, 36, 37]])
array([[11, 36, 19],
       [17, 12, 37],
       [35, 18, 13]])
array([[11,  0,  0],
       [17, 12,  0],
       [35, 18, 13]])
将转换为以下任一阵列:

array([[11, 12, 13],
       [17, 18, 19],
       [35, 36, 37]])
array([[11, 36, 19],
       [17, 12, 37],
       [35, 18, 13]])
array([[11,  0,  0],
       [17, 12,  0],
       [35, 18, 13]])
或者类似于此数组的内容:

array([[11, 12, 13],
       [17, 18, 19],
       [35, 36, 37]])
array([[11, 36, 19],
       [17, 12, 37],
       [35, 18, 13]])
array([[11,  0,  0],
       [17, 12,  0],
       [35, 18, 13]])
取决于我们如何处理边缘。我对边缘行为不太挑剔

下面是我尝试使用的函数:

import numpy

def shear(a, strength=1, shift_axis=0, increase_axis=1, edges='clip'):
    strength = int(strength)
    shift_axis = int(shift_axis)
    increase_axis = int(increase_axis)
    if shift_axis == increase_axis:
        raise UserWarning("Shear can't shift in the direction it increases")
    temp = numpy.zeros(a.shape, dtype=int)
    indices = []
    for d, num in enumerate(a.shape):
        coords = numpy.arange(num)
        shape = [1] * len(a.shape)
        shape[d] = num
        coords = coords.reshape(shape) + temp
        indices.append(coords)
    indices[shift_axis] -= strength * indices[increase_axis]
    if edges == 'clip':
        indices[shift_axis][indices[shift_axis] < 0] = -1
        indices[shift_axis][indices[shift_axis] >= a.shape[shift_axis]] = -1
        res = a[indices]
        res[indices[shift_axis] == -1] = 0
    elif edges == 'roll':
        indices[shift_axis] %= a.shape[shift_axis]
        res = a[indices]
    return res

if __name__ == '__main__':
    a = numpy.random.random((3,4))
    print a
    print shear(a)
导入numpy
def剪切(a,强度=1,位移轴=0,增加轴=1,边缘='clip'):
强度=int(强度)
shift_轴=int(shift_轴)
增加_轴=整数(增加_轴)
如果shift_轴==增加_轴:
raise UserWarning(“剪切力不能沿其增加的方向移动”)
temp=numpy.zero(a.shape,dtype=int)
指数=[]
对于d,枚举中的num(a.shape):
coords=numpy.arange(num)
形状=[1]*len(a.shape)
形状[d]=num
坐标=坐标。重塑(形状)+温度
索引。追加(coords)
指数[shift_轴]-=强度*指数[增加_轴]
如果边==‘剪辑’:
索引[移位轴][索引[移位轴]<0]=-1
索引[shift_轴][索引[shift_轴]>=a.shape[shift_轴]]=-1
res=a[指数]
res[索引[移位轴]=-1]=0
elif边==“滚动”:
索引[shift\u轴]]=a.形状[shift\u轴]
res=a[指数]
返回res
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
a=numpy.random.random((3,4))
打印
印花剪(a)
它似乎起作用了。如果没有,请告诉我

它也显得笨重和不雅。我是否忽略了实现此功能的内置numpy/scipy函数?在numpy有没有更干净/更好/更有效的方法?我是在重新发明轮子吗

编辑:
如果这在N维数组(而不仅仅是2D数组)上有效,则会获得额外点数

这个函数将处于循环的中心,我将在数据处理过程中重复多次,因此我认为它实际上值得优化

第二次编辑: 我终于做了一些基准测试。看起来numpy.roll是一个不错的选择,尽管存在循环。谢谢tom10和Sven Marnach

基准测试代码:(在Windows上运行,我想在Linux上不要使用time.clock)

导入时间,numpy def剪切力_1(a,强度=1,位移_轴=0,增加_轴=1,边缘=滚动): 强度=int(强度) shift_轴=int(shift_轴) 增加_轴=整数(增加_轴) 如果shift_轴==增加_轴: raise UserWarning(“剪切力不能沿其增加的方向移动”) temp=numpy.zero(a.shape,dtype=int) 指数=[] 对于d,枚举中的num(a.shape): coords=numpy.arange(num) 形状=[1]*len(a.shape) 形状[d]=num 坐标=坐标。重塑(形状)+温度 索引。追加(coords) 指数[shift_轴]-=强度*指数[增加_轴] 如果边==‘剪辑’: 索引[移位轴][索引[移位轴]<0]=-1 索引[shift_轴][索引[shift_轴]>=a.shape[shift_轴]]=-1 res=a[指数] res[索引[移位轴]=-1]=0 elif边==“滚动”: 索引[shift\u轴]]=a.形状[shift\u轴] res=a[指数] 返回res def剪切_2(a,强度=1,位移_轴=0,增加_轴=1,边缘=滚动): 索引=numpy.索引(a.形状) 指数[shift_轴]-=强度*指数[增加_轴] 索引[shift\u轴]]=a.形状[shift\u轴] res=a[元组(索引)] 如果边==‘剪辑’: res[索引[移位轴]<0]=0 res[索引[shift_轴]>=a.形状[shift_轴]]=0 返回res def剪切_3(a,强度=1,位移_轴=0,增加_轴=1): 如果shift_轴>增加_轴: 移位_轴-=1 res=numpy.empty_like(a) index=numpy.index\u exp[:]*增加轴 roll=numpy.roll 对于范围内的i(0,a.形状[增加_轴]): 指数i=指数+(i,) res[index_i]=滚动(a[index_i],i*强度,位移轴) 返回res numpy.random.seed(0) 一段时间( numpy.random.random((3,3,3,3)), numpy.random.random((50,50,50,50)), numpy.random.random((300,300,10,10)), ): 打印“数组维度:”,a.shape 对于sa,ia在((0,1)、(1,0)、(2,3)、(0,3))中: 打印“移位轴:”,sa 打印“增加轴:”,ia ref=剪力1(a,位移轴=sa,增加轴=ia) 对于剪力,在((剪力1,'1'),(剪力2,'2'),(剪力3,'3'))中标注: 开始=时间。时钟() b=剪力(a,位移轴=sa,增加轴=ia) end=time.clock() 打印标签+:%0.6f秒“%”(结束-开始) 如果(b-ref).max()大于1e-9: 打印“出问题了。” 打印
我想。你应该考虑这个伪代码多于实际的Python。基本上,对数组进行转置,在其上映射一个通用的旋转函数以进行旋转,然后将其转置回来。

这可以使用中描述的技巧完成:

要获得“剪辑”而不是“滚动”,请使用

这可能是最有效的方法,因为它根本不使用任何Python循环。

numpy就是这样做的。例如,如果原始数组是x,则

for i in range(x.shape[1]):
    x[:,i] = np.roll(x[:,i], i)
产生

[[11 36 19]
 [17 12 37]
 [35 18 13]]

以下是您自己的方法的一个清理版本:

def shear2(a, strength=1, shift_axis=0, increase_axis=1, edges='clip'):
    indices = numpy.indices(a.shape)
    indices[shift_axis] -= strength * indices[increase_axis]
    indices[shift_axis] %= a.shape[shift_axis]
    res = a[tuple(indices)]
    if edges == 'clip':
        res[indices[shift_axis] < 0] = 0
        res[indices[shift_axis] >= a.shape[shift_axis]] = 0
    return res
def-shear2(a,强度=1,位移轴=0,增加轴=1,边缘=clip'):
索引=numpy.索引(a.形状)
指数[shift_轴]-=强度*指数[增加_轴]
索引[shift\u轴]]=a.形状[shift\u轴]
res=a[元组(索引)]
如果边==‘剪辑’:
res[索引[移位轴]<0]=0
res[索引[shift_轴]>=a.形状[shift_轴]]=0
返回res
主要区别在于它使用
numpy.index()
而不是滚动您自己的版本。

中的方法可以扩展到任意维度:

def shear3(a, strength=1, shift_axis=0, increase_axis=1):
    if shift_axis > increase_axis:
        shift_axis -= 1
    res = numpy.empty_like(a)
    index = numpy.index_exp[:] * increase_axis
    roll = numpy.roll
    for i in range(0, a.shape[increase_axis]):
        index_i = index + (i,)
        res[index_i] = roll(a[index_i], -i * strength, shift_axis)
    return res

很不错的!我来试试这个。不要逼我走运,布