2012-10-12 98 views
10

我想創建對應於網格的點的列表。所以如果我想創建一個從(0,0)到(1,1)的區域網格,它將包含點(0,0),(0,1),(1,0),(1, 0)。Numpy meshgrid points

我知道,這可以用下面的代碼來完成:

g = np.meshgrid([0,1],[0,1]) 
np.append(g[0].reshape(-1,1),g[1].reshape(-1,1),axis=1) 

屈服結果:

array([[0, 0], 
     [1, 0], 
     [0, 1], 
     [1, 1]]) 

我的問題是雙重的:

  1. 有沒有更好的這樣做的方式?
  2. 有沒有一種將這種推廣到更高維度的方法?

回答

24

我剛剛注意到,在numpy的文件提供了一種更快的方式做到這一點:

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

這可以很容易地推廣到使用鏈接meshgrid2功能和映射「拉威爾」所得到的電網多個維度。

g = meshgrid2(x, y, z) 
positions = np.vstack(map(np.ravel, g)) 

對於每個軸上有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) 

定義一個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) 

創建網格和時間這兩個功能。

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 
+0

我有一個錯誤消息:'回溯(最近最後調用): 文件 「」,第1行,在 文件 「\ xxx.py」,線路816,在meshgrid2 SLC [I] =透鏡[ i] TypeError:'map'對象不是可以下載的文件'xxx.py'是我放置函數的地方。 –

+0

您可能正在使用python3,其中map返回一個迭代器而不是一個列表。最簡單的做法是將map映射到'list':'lens = list(map(len,arrs))'。 –

+0

Numpy 1.8以上版本不需要'meshgrid2'函數,因爲標準'meshgrid'支持更高的尺寸。 – fhchl

9

您的網格點是不是整數?如果是這樣,你可以使用numpy.ndindex

print list(np.ndindex(2,2)) 

高維:

print list(np.ndindex(2,2,2)) 

不幸的是,這不符合OP的,因爲整體的假設(從0開始)的要求不被滿足。我只會留下這個答案,以防其他人在這些假設是真實的情況下尋找相同的東西。


另一種方式來做到這依賴於zip

g = np.meshgrid([0,1],[0,1]) 
zip(*(x.flat for x in g)) 

該部分很好地擴展到任意尺寸。不幸的是,np.meshgrid不能很好地擴展到多個維度,所以需要制定部分或(假設它有效),您可以使用此SO answer來創建您自己的ndmeshgrid函數。

+0

很好的建議,但遺憾的是他們沒有。編輯...範圍不一定以點(0,0,...)開始。 –

+0

@ Juniper - 太糟糕了。我已經添加了另一個可能有趣的解決方案... – mgilson

+0

這樣做。謝謝! –

1

另一種方式來做到這一點是:

np.indices((2,2)).T.reshape(-1,2) 

哪些可以推廣到更高的層面,例如:

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]])