通过meshgrid数据进行锯齿形的高效,pythonic方式

时间:2017-11-03 21:02:18

标签: python performance numpy

我想制作一个(x,y)点的轨迹,这些点在偶数网格中曲折。我希望能够指定开始的轴。是否有一种有效的方法可以用numpy做到这一点?

例如:

xv, yv = np.meshgrid([1,2,3], [4,5])

产生

xv: [[1 2 3]
     [1 2 3]]
yv: [[4 4 4]
     [5 5 5]]

我希望我的轨迹是:

(1,4), (2,4), (3,4), (3,5), (2,5), (1,5) 

(1,4), (1,5), (2,5), (2,4), (3,4), (3,5)

2 个答案:

答案 0 :(得分:4)

您可以使用以下方法每隔一行翻转坐标:

xv[1::2] = xv[1::2,::-1]

然后堆叠xvyv

xv, yv = np.meshgrid([1,2,3], [4,5])
xv[1::2] = xv[1::2,::-1]

xv
#array([[1, 2, 3],
#       [3, 2, 1]])

np.stack((xv, yv), axis=-1).reshape(-1, 2)

#array([[1, 4],
#       [2, 4],
#       [3, 4],
#       [3, 5],
#       [2, 5],
#       [1, 5]])

或翻转yv

xv, yv = np.meshgrid([1,2,3], [4,5])
yv[:,1::2] = yv[::-1, 1::2]

yv
#array([[4, 5, 4],
#       [5, 4, 5]])

np.stack((xv.T, yv.T), axis=-1).reshape(-1, 2)
#array([[1, 4],
#       [1, 5],
#       [2, 5],
#       [2, 4],
#       [3, 4],
#       [3, 5]])

答案 1 :(得分:3)

我们可以通过直接处理1D数组作为两个输出数组的array-initialization的性能度量来避免创建繁重的meshgrids,然后通过广播的赋值来分配输入数组一次偶数编号的地方,沿着奇数编号的地方翻转。这为我们提供了曲折排序。

实施将是 -

def create_zigzag_grids(a,b):
    m,n = len(b), len(a)

    out1 = np.empty((m,n,2),dtype=int)
    out1[:,:,1] = b[:,None]
    out1[::2,:,0] = a
    out1[1::2,:,0] = a[::-1]

    out2 = np.empty((n,m,2),dtype=int)
    out2[:,:,0] = a[:,None]
    out2[::2,:,1] = b
    out2[1::2,:,1] = b[::-1]
    return out1.reshape(-1,2), out2.reshape(-1,2)

示例运行 -

1)输入和输出:

In [748]: a,b = np.array([1,2,3,4]), np.array([5,6,7])
     ...: out1, out2 = create_zigzag_grids(a,b)
     ...: 

2)创建meshgrid以验证我们的结果:

In [749]: xv, yv = np.meshgrid(a,b)

In [750]: xv
Out[750]: 
array([[1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4]])

In [751]: yv
Out[751]: 
array([[5, 5, 5, 5],
       [6, 6, 6, 6],
       [7, 7, 7, 7]])

3)验证结果:

In [752]: out1
Out[752]: 
array([[1, 5],
       [2, 5],
       [3, 5],
       [4, 5],
       [4, 6],
       [3, 6],
       [2, 6],
       [1, 6],
       [1, 7],
       [2, 7],
       [3, 7],
       [4, 7]])

In [753]: out2
Out[753]: 
array([[1, 5],
       [1, 6],
       [1, 7],
       [2, 7],
       [2, 6],
       [2, 5],
       [3, 5],
       [3, 6],
       [3, 7],
       [4, 7],
       [4, 6],
       [4, 5]])

运行时测试

其他方法 -

def Psidom(a,b): # @Psidom's stack based soln
    xv, yv = np.meshgrid(a,b)
    xv[1::2] = xv[1::2,::-1]
    out1 = np.stack((xv, yv), axis=-1).reshape(-1, 2)
    yv[:,1::2] = yv[::-1, 1::2]
    out2 = np.stack((xv.T, yv.T), axis=-1).reshape(-1, 2)
    return out1, out2 

计时 -

In [829]: a = np.arange(100)
     ...: b = np.arange(100)+100

In [830]: %timeit Psidom(a,b)
     ...: %timeit create_zigzag_grids(a,b)
10000 loops, best of 3: 133 µs per loop
10000 loops, best of 3: 25.1 µs per loop

In [831]: a = np.arange(1000)
     ...: b = np.arange(1000)+1000

In [832]: %timeit Psidom(a,b)
     ...: %timeit create_zigzag_grids(a,b)
10 loops, best of 3: 23.8 ms per loop
100 loops, best of 3: 5.2 ms per loop