2012-10-12 4 views
10

Ich möchte die Liste der Punkte erstellen, die einem Raster entsprechen würde. Wenn ich also ein Gitter der Region von (0,0) bis (1,1) erstellen möchte, würde es die Punkte (0,0), (0,1), (1,0), (1, 0).Numpy Meshgrid Punkte

Ich weiß, daß dies mit dem folgenden Code durchgeführt werden kann:

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

Nachgeben das Ergebnis:

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

Meine Frage ist zweifach:

  1. Gibt es eine bessere Art und Weise dies zu tun?
  2. Gibt es eine Möglichkeit, dies zu höheren Dimensionen zu verallgemeinern?

Antwort

24

Ich habe gerade bemerkt, dass die Dokumentation in numpy eine noch schnellere Möglichkeit bietet, dies zu tun:

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

Dies kann leicht auf mehr Dimensionen verallgemeinert werden, mit der verknüpften meshgrid2 Funktion und Kartierung ‚ravel‘ zu dem resultierenden Gitter .

Das Ergebnis ist etwa 35 Mal schneller als die Zip-Methode für ein 3D-Array mit 1000 Ticks auf jeder Achse.

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

Zum Vergleich der beiden Methoden die folgenden Abschnitte des Codes berücksichtigen:

Erstellen Sie die sprichwörtlich Strichmarkierungen, die das Raster erstellen helfen.

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) 

die Funktion definieren, die für die meshgrid verknüpft mgilson:

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) 

das Gitter und die Zeit der beiden Funktionen erstellen.

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

Ich habe eine Fehlermeldung: 'Traceback (jüngste Aufforderung zuletzt): File "" Linie 1 in File " \ xxx.py", Linie 816, in meshgrid2 slc [i] = Objektiv [ i] TypeError: 'map' -Objekt ist nicht subscriptfähig 'file' xxx.py' ist der Ort, an den ich Ihre Funktion einfüge. –

+0

Wahrscheinlich verwenden Sie python3, wobei map einen Iterator statt einer Liste zurückgibt. Am einfachsten ist es, 'map' in' list' zu schreiben: 'lens = list (map (len, arrs))'. –

+0

Oberhalb von Numpy 1.8 ist die Funktion 'meshgrid2' nicht erforderlich, da das Standard' meshgrid' höhere Dimensionen unterstützt. – fhchl

9

Sind Ihre Netzpunkte immer integriert? Wenn ja, könnten Sie numpy.ndindex

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

Höhere Dimensionen verwenden:

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

Leider ist dies entspricht nicht den Anforderungen des OP seit dem Integral Annahme (beginnend mit 0) nicht erfüllt . Ich lasse diese Antwort nur für den Fall, dass jemand anderes nach dem gleichen sucht, wo diese Annahmen wahr sind.


Ein anderer Weg, dies zu tun, beruht auf zip:

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

Dieser Teil skaliert gut auf beliebige Dimensionen. Leider np.meshgrid skaliert nicht gut zu mehreren Dimensionen, so dass Teil muss ausgearbeitet werden, oder (vorausgesetzt, es funktioniert), können Sie diese SO answer verwenden, um Ihre eigene ndmeshgrid-Funktion zu erstellen.

+0

Guter Vorschlag, aber leider sind sie nicht. Bearbeiten ... auch die Bereiche müssen nicht unbedingt mit dem Punkt (0,0, ...) beginnen. –

+0

@juniper - Schade. Ich habe eine andere Lösung hinzugefügt, die von Interesse sein könnte ... – mgilson

+0

Das reicht. Vielen Dank! –

1

Noch ein anderer Weg, es zu tun ist:

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

die zu höheren Dimensionen verallgemeinert werden können, z.B .:

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