Python 剪切numpy数组
我想“剪切”一个numpy数组。我不确定我是否正确使用了“剪切”一词;我所说的剪切是指: 将第一列移动0位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,
将第二列移动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
很不错的!我来试试这个。不要逼我走运,布