Numpy meshgrid点

jun*_*er- 15 python numpy

我想创建与网格对应的点列表.因此,如果我想创建从(0,0)到(1,1)的区域网格,它将包含点(0,0),(0,1),(1,0),(1, 0).

我知道这可以通过以下代码完成:

g = np.meshgrid([0,1],[0,1])
np.append(g[0].reshape(-1,1),g[1].reshape(-1,1),axis=1)
Run Code Online (Sandbox Code Playgroud)

产生结果:

array([[0, 0],
       [1, 0],
       [0, 1],
       [1, 1]])
Run Code Online (Sandbox Code Playgroud)

我的问题是双重的:

  1. 有没有更好的方法呢?
  2. 有没有办法将其推广到更高的维度?

jun*_*er- 32

我刚刚注意到numpy中的文档提供了一种更快的方法:

X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([X.ravel(), Y.ravel()])
Run Code Online (Sandbox Code Playgroud)

使用链接的meshgrid2函数并将"ravel"映射到结果网格,可以很容易地将其推广到更多维度.

g = meshgrid2(x, y, z)
positions = np.vstack(map(np.ravel, g))
Run Code Online (Sandbox Code Playgroud)

对于每个轴上有1000个刻度的3D阵列,结果比zip方法快35倍.

来源:http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html#scipy.stats.gaussian_kde

要比较这两种方法,请考虑以下代码部分:

创建有助于创建网格的众所周知的刻度线.

In [23]: import numpy as np

In [34]: from numpy import asarray

In [35]: x = np.random.rand(100,1)

In [36]: y = np.random.rand(100,1)

In [37]: z = np.random.rand(100,1)
Run Code Online (Sandbox Code Playgroud)

定义mgilson链接到meshgrid的函数:

In [38]: def meshgrid2(*arrs):
   ....:     arrs = tuple(reversed(arrs))
   ....:     lens = map(len, arrs)
   ....:     dim = len(arrs)
   ....:     sz = 1
   ....:     for s in lens:
   ....:        sz *= s
   ....:     ans = []
   ....:     for i, arr in enumerate(arrs):
   ....:         slc = [1]*dim
   ....:         slc[i] = lens[i]
   ....:         arr2 = asarray(arr).reshape(slc)
   ....:         for j, sz in enumerate(lens):
   ....:             if j != i:
   ....:                 arr2 = arr2.repeat(sz, axis=j)
   ....:         ans.append(arr2)
   ....:     return tuple(ans)
Run Code Online (Sandbox Code Playgroud)

创建网格并计算两个函数的时间.

In [39]: g = meshgrid2(x, y, z)

In [40]: %timeit pos = np.vstack(map(np.ravel, g)).T
100 loops, best of 3: 7.26 ms per loop

In [41]: %timeit zip(*(x.flat for x in g))
1 loops, best of 3: 264 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • Numpy 1.8 以上不再需要 `meshgrid2` 函数,因为标准 `meshgrid` 支持更高的维度。 (5认同)
  • 使用Python 3.8.10 @juniper- 指出的解决方案并不完全适合我。我需要更改 `positions = np.vstack(list(zip(X.ravel(), Y.ravel())))` (2认同)

mgi*_*son 16

你的网格点总是不可分割的吗?如果是这样,你可以使用numpy.ndindex

print list(np.ndindex(2,2))
Run Code Online (Sandbox Code Playgroud)

更高的尺寸:

print list(np.ndindex(2,2,2))
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不符合OP的要求,因为不满足积分假设(从0开始).我会留下这个答案,以防万一其他人正在寻找那些假设属实的东西.


另一种方法依赖于zip:

g = np.meshgrid([0,1],[0,1])
zip(*(x.flat for x in g))
Run Code Online (Sandbox Code Playgroud)

这部分很好地适应任意尺寸.不幸的是,np.meshgrid不能很好地扩展到多个维度,因此需要解决该部分,或者(假设它有效),您可以使用此SO答案来创建自己的ndmeshgrid函数.


小智 5

另一种方法是:

np.indices((2,2)).T.reshape(-1,2)
Run Code Online (Sandbox Code Playgroud)

可以推广到更高的维度,例如:

In [60]: np.indices((2,2,2)).T.reshape(-1,3)
Out[60]:
array([[0, 0, 0],
       [1, 0, 0],
       [0, 1, 0],
       [1, 1, 0],
       [0, 0, 1],
       [1, 0, 1],
       [0, 1, 1],
       [1, 1, 1]])
Run Code Online (Sandbox Code Playgroud)