2009-12-01 12 views
36

Numpys Meshgrid ist sehr nützlich, um zwei Vektoren in ein Koordinatengitter zu konvertieren. Was ist der einfachste Weg, um dies auf drei Dimensionen zu erweitern? Wenn drei Vektoren x, y und z gegeben sind, konstruiere 3x3D-Arrays (anstelle von 2x2D-Arrays), die als Koordinaten verwendet werden können.Numpy Meshgrid in 3D

Antwort

26

ist der Quellcode von meshgrid:

def meshgrid(x,y): 
    """ 
    Return coordinate matrices from two coordinate vectors. 

    Parameters 
    ---------- 
    x, y : ndarray 
     Two 1-D arrays representing the x and y coordinates of a grid. 

    Returns 
    ------- 
    X, Y : ndarray 
     For vectors `x`, `y` with lengths ``Nx=len(x)`` and ``Ny=len(y)``, 
     return `X`, `Y` where `X` and `Y` are ``(Ny, Nx)`` shaped arrays 
     with the elements of `x` and y repeated to fill the matrix along 
     the first dimension for `x`, the second for `y`. 

    See Also 
    -------- 
    index_tricks.mgrid : Construct a multi-dimensional "meshgrid" 
         using indexing notation. 
    index_tricks.ogrid : Construct an open multi-dimensional "meshgrid" 
         using indexing notation. 

    Examples 
    -------- 
    >>> X, Y = np.meshgrid([1,2,3], [4,5,6,7]) 
    >>> X 
    array([[1, 2, 3], 
      [1, 2, 3], 
      [1, 2, 3], 
      [1, 2, 3]]) 
    >>> Y 
    array([[4, 4, 4], 
      [5, 5, 5], 
      [6, 6, 6], 
      [7, 7, 7]]) 

    `meshgrid` is very useful to evaluate functions on a grid. 

    >>> x = np.arange(-5, 5, 0.1) 
    >>> y = np.arange(-5, 5, 0.1) 
    >>> xx, yy = np.meshgrid(x, y) 
    >>> z = np.sin(xx**2+yy**2)/(xx**2+yy**2) 

    """ 
    x = asarray(x) 
    y = asarray(y) 
    numRows, numCols = len(y), len(x) # yes, reversed 
    x = x.reshape(1,numCols) 
    X = x.repeat(numRows, axis=0) 

    y = y.reshape(numRows,1) 
    Y = y.repeat(numCols, axis=1) 
    return X, Y 

Es ist ziemlich einfach zu verstehen. Ich habe das Muster auf eine beliebige Anzahl von Dimensionen erweitert, aber dieser Code ist keineswegs optimiert (und auch nicht gründlich mit Fehlern versehen), aber Sie bekommen, wofür Sie bezahlen. Hoffe, es hilft:

def meshgrid2(*arrs): 
    arrs = tuple(reversed(arrs)) #edit 
    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) 
+1

Im Falle eines 3D-Mesh-Gitters, das ein Beispiel wie das in numpy doc für Meshgrib verwendete verwendet, würde dies Z, Y, X anstelle von X, Y, Z zurückgeben. Ersetzen Sie die Rückgabeanweisung durch 'return tuple (ans [[- 1])' 'kann dies beheben. – levesque

+0

@Paul Wenn die Länge des X- oder Y-Arrays lang ist, stürzt der x.repeat() -Befehl ab und sendet einen Speicherfehler. Gibt es eine Möglichkeit, diesen Fehler zu vermeiden? – Dalek

+0

@Dalek Wie lang sind die Arrays? Könnte es sein, dass dir der Speicher ausgeht? Wenn beispielsweise 3 Arrays vorhanden sind und jeweils 4096 Einträge vorhanden sind und jeder Eintrag ein Double (dh 8 Bytes) enthält, benötigen wir für Einträge allein (8 * 4 * 2 ** 10) ** 3 Bytes = 2 ** 45 Bytes = 32 * 2 ** 40 Bytes = 32 TB Speicher, was offensichtlich enorm ist. Ich hoffe, ich habe hier keinen Fehler gemacht. –

5

ich denke, was Sie wollen, ist

X, Y, Z = numpy.mgrid[-10:10:100j, -10:10:100j, -10:10:100j] 

zum Beispiel.

+0

Danke, aber das ist nicht ganz das, was Ich brauche - Meshgrid verwendet tatsächlich die Werte der Vektoren, um das 2D-Array zu generieren, und die Werte können unregelmäßig verteilt sein. – astrofrog

7

Können Sie uns zeigen, wie Sie np.meshgrid verwenden? Es besteht eine sehr gute Chance, dass Sie Meshgrid wirklich nicht brauchen, weil numpy Broadcasting dasselbe tun kann, ohne ein sich wiederholendes Array zu erzeugen.

Zum Beispiel

import numpy as np 

x=np.arange(2) 
y=np.arange(3) 
[X,Y] = np.meshgrid(x,y) 
S=X+Y 

print(S.shape) 
# (3, 2) 
# Note that meshgrid associates y with the 0-axis, and x with the 1-axis. 

print(S) 
# [[0 1] 
# [1 2] 
# [2 3]] 

s=np.empty((3,2)) 
print(s.shape) 
# (3, 2) 

# x.shape is (2,). 
# y.shape is (3,). 
# x's shape is broadcasted to (3,2) 
# y varies along the 0-axis, so to get its shape broadcasted, we first upgrade it to 
# have shape (3,1), using np.newaxis. Arrays of shape (3,1) can be broadcasted to 
# arrays of shape (3,2). 
s=x+y[:,np.newaxis] 
print(s) 
# [[0 1] 
# [1 2] 
# [2 3]] 

Der Punkt ist, dass S=X+Y kann und sollte durch s=x+y[:,np.newaxis] ersetzt werden, da letztere nicht erfordert (möglicherweise große) sich wiederholenden Anordnungen gebildet werden. Es verallgemeinert sich auch leicht zu höheren Dimensionen (mehr Achsen). Fügen Sie einfach np.newaxis hinzu, um die Übertragung nach Bedarf auszuführen.

Weitere Informationen zum Senden von Nachrichten finden Sie unter http://www.scipy.org/EricsBroadcastingDoc. Hier

4

Statt eine neue Funktion zu schreiben, sollte numpy.ix_ tun, was Sie wollen.

Hier ist ein Beispiel aus der Dokumentation:

>>> ixgrid = np.ix_([0,1], [2,4]) 
>>> ixgrid 
(array([[0], 
    [1]]), array([[2, 4]])) 
>>> ixgrid[0].shape, ixgrid[1].shape 
((2, 1), (1, 2))' 
+4

wäre es schön, wenn Sie sagen könnten, wie? ... –

4

Hier eine mehrdimensionale Version von meshgrid ist, die ich schrieb:

def ndmesh(*args): 
    args = map(np.asarray,args) 
    return np.broadcast_arrays(*[x[(slice(None),)+(None,)*i] for i, x in enumerate(args)]) 

Beachten Sie, dass die zurückgegebenen Arrays Ansichten der ursprünglichen Array-Daten sind, Das Ändern der ursprünglichen Arrays wirkt sich also auf die Koordinatenfelder aus.

+0

hat den Trick für mich, vielen Dank! – somada141

31

Numpy (ab 1.8 denke ich) unterstützt jetzt höher, dass 2D-Generation von Positionsgittern mit meshgrid. Eine wichtige Ergänzung, die mir wirklich geholfen ist die Fähigkeit, die Indizierung, um zu wählen (entweder xy oder ij für cartesianischen oder Matrixindizierung jeweils), die ich mit dem folgende Beispiel überprüft:

import numpy as np 

x_ = np.linspace(0., 1., 10) 
y_ = np.linspace(1., 2., 20) 
z_ = np.linspace(3., 4., 30) 

x, y, z = np.meshgrid(x_, y_, z_, indexing='ij') 

assert np.all(x[:,0,0] == x_) 
assert np.all(y[0,:,0] == y_) 
assert np.all(z[0,0,:] == z_) 
Verwandte Themen