¿Cuál es el propósito de meshgrid en Python / NumPy?

303

¿Alguien puede explicarme cuál es el propósito de la meshgridfunción en Numpy? Sé que crea algún tipo de cuadrícula de coordenadas para trazar, pero realmente no puedo ver el beneficio directo de ello.

Estoy estudiando "Python Machine Learning" de Sebastian Raschka, y él lo está usando para trazar los límites de decisión. Vea la entrada 11 aquí .

También probé este código de la documentación oficial, pero, una vez más, el resultado realmente no tiene sentido para mí.

x = np.arange(-5, 5, 1)
y = np.arange(-5, 5, 1)
xx, yy = np.meshgrid(x, y, sparse=True)
z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)
h = plt.contourf(x,y,z)

Por favor, si es posible, muéstrame muchos ejemplos del mundo real.

HonzaB
fuente

Respuestas:

391

El propósito de meshgrides crear una cuadrícula rectangular a partir de una matriz de valores xy una matriz de valores y.

Entonces, por ejemplo, si queremos crear una cuadrícula donde tengamos un punto en cada valor entero entre 0 y 4 en las direcciones x e y. Para crear una cuadrícula rectangular, necesitamos todas las combinaciones de los puntos xy y.

Esto va a ser 25 puntos, ¿verdad? Entonces, si quisiéramos crear una matriz x e y para todos estos puntos, podríamos hacer lo siguiente.

x[0,0] = 0    y[0,0] = 0
x[0,1] = 1    y[0,1] = 0
x[0,2] = 2    y[0,2] = 0
x[0,3] = 3    y[0,3] = 0
x[0,4] = 4    y[0,4] = 0
x[1,0] = 0    y[1,0] = 1
x[1,1] = 1    y[1,1] = 1
...
x[4,3] = 3    y[4,3] = 4
x[4,4] = 4    y[4,4] = 4

Esto daría como resultado las siguientes xy ymatrices, de modo que el emparejamiento del elemento correspondiente en cada matriz da las coordenadas x e y de un punto en la cuadrícula.

x =   0 1 2 3 4        y =   0 0 0 0 0
      0 1 2 3 4              1 1 1 1 1
      0 1 2 3 4              2 2 2 2 2
      0 1 2 3 4              3 3 3 3 3
      0 1 2 3 4              4 4 4 4 4

Luego podemos trazar estos para verificar que son una cuadrícula:

plt.plot(x,y, marker='.', color='k', linestyle='none')

ingrese la descripción de la imagen aquí

Obviamente, esto se vuelve muy tedioso, especialmente para grandes rangos de xy y. En cambio, en meshgridrealidad puede generar esto para nosotros: todo lo que tenemos que especificar son los valores únicos xy únicos y.

xvalues = np.array([0, 1, 2, 3, 4]);
yvalues = np.array([0, 1, 2, 3, 4]);

Ahora, cuando llamamos meshgrid, obtenemos la salida anterior automáticamente.

xx, yy = np.meshgrid(xvalues, yvalues)

plt.plot(xx, yy, marker='.', color='k', linestyle='none')

ingrese la descripción de la imagen aquí

La creación de estas cuadrículas rectangulares es útil para una serie de tareas. En el ejemplo que ha proporcionado en su publicación, es simplemente una forma de muestrear una función ( sin(x**2 + y**2) / (x**2 + y**2)) en un rango de valores para xy y.

Debido a que esta función se ha muestreado en una cuadrícula rectangular, la función ahora se puede visualizar como una "imagen".

ingrese la descripción de la imagen aquí

Además, el resultado ahora se puede pasar a funciones que esperan datos en una cuadrícula rectangular (es decir contourf)

Suever
fuente
10
No ha explicado los valores de retorno xxy yy. La parte misteriosa para mí fue por qué devuelve ese par de resultados y cómo se ven. La respuesta de Hai Phan es útil para eso. Supongo que lo hace por conveniencia, ya que plot quiere dos parámetros como ese.
nealmcb
2
No lo sé, es por eso que estoy buscando esta información;) Así que no digo que deba devolver algo diferente. Solo estoy dando mi mejor suposición a una información faltante para aquellos que acaban de leer la respuesta aceptada. Y si lo desea, sugiero que su respuesta (que ya es muy agradable, ¡gracias!) Sería un poco más completa si explicara los valores de retorno (como lo hizo Hai), para aquellos de nosotros que todavía estamos desconcertados.
nealmcb
1
Para comprender mejor los valores de xx e yy, considere la afirmación de que el siguiente código le da el mismo resultado que np.meshgrid:xx = [xvalues for y in yvalues] yy = [[y for x in xvalues] for y in yvalues]
Matt Kleinsmith
1
Esta respuesta es confusa: ¿no es tu primera ilustración de xy yhacia atrás? Cuando lo haces xx, yy = np.meshgrid(np.arange(4), np.arange(4)), es lo contrario de lo que tienes xy yen la primera parte de la respuesta. mgridCoincide con el orden de las salidas para , pero no meshgrid. El xxdebería estar aumentando en la dirección x, pero el tuyo aumenta en la dirección y.
Scott Staniewicz
1
@ScottStaniewicz Gracias por señalar que nuestro, ahora seguro de cómo lo estropeé ... ¡Actualizado!
Suever
249

Cortesía de Microsoft Excel: 

ingrese la descripción de la imagen aquí

Zarzaparrilla
fuente
66
Agradable. Fwiw, si quieres una matriz de 2 x 12 de los pares en el medio:XYpairs = np.vstack([ XX.reshape(-1), YY.reshape(-1) ])
denis
55
y si quieres una matriz de 12 x 2 de los pares en el medio:XYpairs = np.dstack([XX, YY]).reshape(-1, 2)
barlaensdoonn
2
Buena respuesta. El propósito de meshgrid es crear una cuadrícula utilizando la coordenada de cada dim.
Buen chico
1
Lo que me parece un poco extraño es que los valores x e y se devuelven por separado en lugar de ya combinados en una matriz. Si los quiero en una matriz, tengo que hacer:np.vstack([XX.ravel(), YY.ravel()]).T
user3629892
66

En realidad, el propósito de np.meshgridya se menciona en la documentación:

np.meshgrid

Devuelve matrices de coordenadas de vectores de coordenadas.

Realice matrices de coordenadas ND para evaluaciones vectorizadas de campos escalares / vectoriales ND sobre cuadrículas ND, dados los conjuntos de coordenadas unidimensionales x1, x2, ..., xn.

Por lo tanto, su objetivo principal es crear matrices de coordenadas.

Probablemente te hayas preguntado a ti mismo:

¿Por qué necesitamos crear matrices de coordenadas?

La razón por la que necesita matrices de coordenadas con Python / NumPy es que no hay una relación directa de coordenadas a valores, excepto cuando sus coordenadas comienzan con cero y son enteros puramente positivos. Entonces puede usar los índices de una matriz como índice. Sin embargo, cuando ese no es el caso, de alguna manera necesita almacenar coordenadas junto con sus datos. Ahí es donde entran las cuadrículas.

Supongamos que sus datos son:

1  2  1
2  5  2
1  2  1

Sin embargo, cada valor representa una región de 2 kilómetros de ancho horizontalmente y 3 kilómetros verticalmente. Suponga que su origen es la esquina superior izquierda y desea matrices que representen la distancia que podría usar:

import numpy as np
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)

donde v es:

array([[0, 0, 0],
       [2, 2, 2],
       [4, 4, 4]])

y h:

array([[0, 3, 6],
       [0, 3, 6],
       [0, 3, 6]])

Entonces, si tiene dos índices, digamos xy y(es por eso que el valor de retorno de meshgridusualmente xxo en xslugar de xen este caso elijo hhorizontalmente), entonces puede obtener la coordenada x del punto, la coordenada y del punto y el valor en ese punto usando:

h[x, y]    # horizontal coordinate
v[x, y]    # vertical coordinate
data[x, y]  # value

Eso hace que sea mucho más fácil hacer un seguimiento de las coordenadas y (aún más importante) puede pasarlas a funciones que necesitan conocer las coordenadas.

Una explicación un poco más larga.

Sin embargo, np.meshgrida menudo no se usa directamente, en su mayoría solo se usa uno de objetos similaresnp.mgrid o np.ogrid. Aquí np.mgridrepresenta el sparse=Falsey np.ogridel sparse=Truecaso (me refiero al sparseargumento del np.meshgrid). Tenga en cuenta que hay una diferencia significativa entre np.meshgridy np.ogridynp.mgrid : Los dos primeros valores devueltos (si hay dos o más) se invierten. A menudo, esto no importa, pero debe dar nombres de variables significativos según el contexto.

Por ejemplo, en el caso de una cuadrícula 2D y matplotlib.pyplot.imshowtiene sentido nombrar el primer elemento devuelto de np.meshgrid xy el segundo ymientras es al revés para np.mgridy np.ogrid.

np.ogrid y rejillas dispersas

>>> import numpy as np
>>> yy, xx = np.ogrid[-5:6, -5:6]
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5],
       [-4],
       [-3],
       [-2],
       [-1],
       [ 0],
       [ 1],
       [ 2],
       [ 3],
       [ 4],
       [ 5]])
       

Como ya se dijo, la salida se invierte en comparación con np.meshgrid, por eso lo desempaqué como en yy, xxlugar de xx, yy:

>>> xx, yy = np.meshgrid(np.arange(-5, 6), np.arange(-5, 6), sparse=True)
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5],
       [-4],
       [-3],
       [-2],
       [-1],
       [ 0],
       [ 1],
       [ 2],
       [ 3],
       [ 4],
       [ 5]])

Esto ya parece coordenadas, específicamente las líneas x e y para gráficos 2D.

Visualizado:

yy, xx = np.ogrid[-5:6, -5:6]
plt.figure()
plt.title('ogrid (sparse meshgrid)')
plt.grid()
plt.xticks(xx.ravel())
plt.yticks(yy.ravel())
plt.scatter(xx, np.zeros_like(xx), color="blue", marker="*")
plt.scatter(np.zeros_like(yy), yy, color="red", marker="x")

ingrese la descripción de la imagen aquí

np.mgrid y rejillas densas / desarrolladas

>>> yy, xx = np.mgrid[-5:6, -5:6]
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5],
       [-4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4],
       [-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3],
       [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
       [ 2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2],
       [ 3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3],
       [ 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4],
       [ 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5]])
       

Lo mismo se aplica aquí: la salida se invierte en comparación con np.meshgrid:

>>> xx, yy = np.meshgrid(np.arange(-5, 6), np.arange(-5, 6))
>>> xx
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5]])
>>> yy
array([[-5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5],
       [-4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4],
       [-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3],
       [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
       [ 2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2],
       [ 3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3],
       [ 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4],
       [ 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5]])
       

A diferencia de ogridestas matrices contienen todas xx y yycoordenadas en -5 <= xx <= 5; -5 <= aa <= 5 cuadrícula.

yy, xx = np.mgrid[-5:6, -5:6]
plt.figure()
plt.title('mgrid (dense meshgrid)')
plt.grid()
plt.xticks(xx[0])
plt.yticks(yy[:, 0])
plt.scatter(xx, yy, color="red", marker="x")

ingrese la descripción de la imagen aquí

Funcionalidad

No solo se limita a 2D, estas funciones funcionan para dimensiones arbitrarias (bueno, hay un número máximo de argumentos dados para funcionar en Python y un número máximo de dimensiones que NumPy permite):

>>> x1, x2, x3, x4 = np.ogrid[:3, 1:4, 2:5, 3:6]
>>> for i, x in enumerate([x1, x2, x3, x4]):
...     print('x{}'.format(i+1))
...     print(repr(x))
x1
array([[[[0]]],


       [[[1]]],


       [[[2]]]])
x2
array([[[[1]],

        [[2]],

        [[3]]]])
x3
array([[[[2],
         [3],
         [4]]]])
x4
array([[[[3, 4, 5]]]])

>>> # equivalent meshgrid output, note how the first two arguments are reversed and the unpacking
>>> x2, x1, x3, x4 = np.meshgrid(np.arange(1,4), np.arange(3), np.arange(2, 5), np.arange(3, 6), sparse=True)
>>> for i, x in enumerate([x1, x2, x3, x4]):
...     print('x{}'.format(i+1))
...     print(repr(x))
# Identical output so it's omitted here.

Incluso si estos también funcionan para 1D, hay dos funciones de creación de cuadrícula 1D (mucho más comunes):

Además del argumento starty stop, también admite el stepargumento (incluso pasos complejos que representan el número de pasos):

>>> x1, x2 = np.mgrid[1:10:2, 1:10:4j]
>>> x1  # The dimension with the explicit step width of 2
array([[1., 1., 1., 1.],
       [3., 3., 3., 3.],
       [5., 5., 5., 5.],
       [7., 7., 7., 7.],
       [9., 9., 9., 9.]])
>>> x2  # The dimension with the "number of steps"
array([[ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.]])
       

Aplicaciones

Usted preguntó específicamente sobre el propósito y, de hecho, estas cuadrículas son extremadamente útiles si necesita un sistema de coordenadas.

Por ejemplo, si tiene una función NumPy que calcula la distancia en dos dimensiones:

def distance_2d(x_point, y_point, x, y):
    return np.hypot(x-x_point, y-y_point)
    

Y quieres saber la distancia de cada punto:

>>> ys, xs = np.ogrid[-5:5, -5:5]
>>> distances = distance_2d(1, 2, xs, ys)  # distance to point (1, 2)
>>> distances
array([[9.21954446, 8.60232527, 8.06225775, 7.61577311, 7.28010989,
        7.07106781, 7.        , 7.07106781, 7.28010989, 7.61577311],
       [8.48528137, 7.81024968, 7.21110255, 6.70820393, 6.32455532,
        6.08276253, 6.        , 6.08276253, 6.32455532, 6.70820393],
       [7.81024968, 7.07106781, 6.40312424, 5.83095189, 5.38516481,
        5.09901951, 5.        , 5.09901951, 5.38516481, 5.83095189],
       [7.21110255, 6.40312424, 5.65685425, 5.        , 4.47213595,
        4.12310563, 4.        , 4.12310563, 4.47213595, 5.        ],
       [6.70820393, 5.83095189, 5.        , 4.24264069, 3.60555128,
        3.16227766, 3.        , 3.16227766, 3.60555128, 4.24264069],
       [6.32455532, 5.38516481, 4.47213595, 3.60555128, 2.82842712,
        2.23606798, 2.        , 2.23606798, 2.82842712, 3.60555128],
       [6.08276253, 5.09901951, 4.12310563, 3.16227766, 2.23606798,
        1.41421356, 1.        , 1.41421356, 2.23606798, 3.16227766],
       [6.        , 5.        , 4.        , 3.        , 2.        ,
        1.        , 0.        , 1.        , 2.        , 3.        ],
       [6.08276253, 5.09901951, 4.12310563, 3.16227766, 2.23606798,
        1.41421356, 1.        , 1.41421356, 2.23606798, 3.16227766],
       [6.32455532, 5.38516481, 4.47213595, 3.60555128, 2.82842712,
        2.23606798, 2.        , 2.23606798, 2.82842712, 3.60555128]])
        

La salida sería idéntica si se pasara en una grilla densa en lugar de una grilla abierta. ¡La transmisión de NumPys lo hace posible!

Visualicemos el resultado:

plt.figure()
plt.title('distance to point (1, 2)')
plt.imshow(distances, origin='lower', interpolation="none")
plt.xticks(np.arange(xs.shape[1]), xs.ravel())  # need to set the ticks manually
plt.yticks(np.arange(ys.shape[0]), ys.ravel())
plt.colorbar()

ingrese la descripción de la imagen aquí

Y esto también es cuando NumPys mgridy se ogridvuelve muy conveniente porque le permite cambiar fácilmente la resolución de sus cuadrículas:

ys, xs = np.ogrid[-5:5:200j, -5:5:200j]
# otherwise same code as above

ingrese la descripción de la imagen aquí

Sin embargo, dado imshowque no admite xe yingresa, uno tiene que cambiar los ticks a mano. Sería realmente conveniente si aceptara el xyy coordenadas , ¿verdad?

Es fácil escribir funciones con NumPy que tratan naturalmente con cuadrículas. Además, hay varias funciones en NumPy, SciPy, matplotlib que esperan que pase en la cuadrícula.

Me gustan las imágenes, así que exploremos matplotlib.pyplot.contour:

ys, xs = np.mgrid[-5:5:200j, -5:5:200j]
density = np.sin(ys)-np.cos(xs)
plt.figure()
plt.contour(xs, ys, density)

ingrese la descripción de la imagen aquí

¡Observe cómo las coordenadas ya están configuradas correctamente! Ese no sería el caso si acabaras de pasar density.

O para dar otro ejemplo divertido usando modelos de astropía (esta vez no me importan mucho las coordenadas, solo las uso para crear una cuadrícula):

from astropy.modeling import models
z = np.zeros((100, 100))
y, x = np.mgrid[0:100, 0:100]
for _ in range(10):
    g2d = models.Gaussian2D(amplitude=100, 
                           x_mean=np.random.randint(0, 100), 
                           y_mean=np.random.randint(0, 100), 
                           x_stddev=3, 
                           y_stddev=3)
    z += g2d(x, y)
    a2d = models.AiryDisk2D(amplitude=70, 
                            x_0=np.random.randint(0, 100), 
                            y_0=np.random.randint(0, 100), 
                            radius=5)
    z += a2d(x, y)
    

ingrese la descripción de la imagen aquí

Aunque eso es solo "por el aspecto", varias funciones relacionadas con modelos funcionales y ajuste (por ejemplo scipy.interpolate.interp2d, scipy.interpolate.griddataincluso mostrar ejemplos usando np.mgrid) en Scipy, etc. requieren cuadrículas. La mayoría de estos funcionan con rejillas abiertas y rejillas densas, sin embargo, algunos solo funcionan con uno de ellos.

MSeifert
fuente
Solo quiero agradecer enormemente esta respuesta extremadamente detallada. Esto hizo mi dia.
Jlanger
Qué hermosa forma de responder una pregunta ... tan detallado. Gracias
Bipin
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)- Dado que sus 2 km horizontales y 3 km verticales, ¿no debería multiplicarse el primer rango por 2 y el segundo por 3?
Nixt
@Nixt Lamentablemente, no es tan simple como eso. Puede que tenga que verificar esa parte de la respuesta nuevamente. Es una compensación entre la visualización transpuesta de la matriz y la indexación inversa; normalmente, se espera que el primer índice sea horizontal y el segundo vertical, pero luego la pantalla se transpondrá. Sin embargo, este es principalmente un detalle que, con suerte, no invalida la esencia de la respuesta, cuyo objetivo es ilustrar el motivo de las cuadrículas. Pero intentaré revisar esto en una fecha futura.
MSeifert
36

Supongamos que tiene una función:

def sinus2d(x, y):
    return np.sin(x) + np.sin(y)

y desea, por ejemplo, ver cómo se ve en el rango de 0 a 2 * pi. ¿Como lo harias? No np.meshgridviene en:

xx, yy = np.meshgrid(np.linspace(0,2*np.pi,100), np.linspace(0,2*np.pi,100))
z = sinus2d(xx, yy) # Create the image on this grid

y esa trama se vería así:

import matplotlib.pyplot as plt
plt.imshow(z, origin='lower', interpolation='none')
plt.show()

ingrese la descripción de la imagen aquí

Entonces np.meshgrides solo una conveniencia. En principio, lo mismo podría hacerse:

z2 = sinus2d(np.linspace(0,2*np.pi,100)[:,None], np.linspace(0,2*np.pi,100)[None,:])

pero allí debe conocer sus dimensiones (suponga que tiene más de dos ...) y la transmisión correcta. np.meshgridhace todo esto por ti.

También meshgrid le permite eliminar coordenadas junto con los datos si, por ejemplo, desea hacer una interpolación pero excluye ciertos valores:

condition = z>0.6
z_new = z[condition] # This will make your array 1D

Entonces, ¿cómo harías la interpolación ahora? Usted puede dar xy yde una función de interpolación como scipy.interpolate.interp2dpor lo que necesita una manera de saber qué coordenadas se han eliminado:

x_new = xx[condition]
y_new = yy[condition]

y aún puede interpolar con las coordenadas "correctas" (pruébelo sin la malla y tendrá mucho código extra):

from scipy.interpolate import interp2d
interpolated = interp2d(x_new, y_new, z_new)

y el meshgrid original le permite obtener la interpolación en el grid original nuevamente:

interpolated_grid = interpolated(xx[0], yy[:, 0]).reshape(xx.shape)

Estos son solo algunos ejemplos en los que usé el meshgridque podría haber mucho más.

MSeifert
fuente
1
¡Gracias por su respuesta! El momento más confuso para mí se volvió valores xx, yy. Fue difícil entender qué son y por qué los usamos para calcular la función. Parece que lo tengo. Queremos calcular alguna función basada en coordenadas. Podemos escribir algo como esto: en su for x=1:10: for y=1:10: z[x,y]=sin(x)+sin(y)lugar, calculamos zde una manera diferente z=sin([x,x,...,x]) + sin([y,y,..y]). ¡Corrígeme si estoy equivocado!
Alena Kastsiukavets
No es un pseudocódigo 100% correcto, pero espero que
entiendas
En realidad, siempre necesitas el doble bucle (tu primer código). Pero hay diferentes formas de archivarlo numpy: meshgrid o broadcasting. Si no descarta puntos (vea la última parte de mi respuesta), ambos son funcionalmente equivalentes. La radiodifusión es solo un bucle implícito en la dimensión a ser transmitida. Tenga en cuenta que he utilizado [:,None]y [None, :]que incluyo dimensiones extra por lo que el resultado transmite correctamente. Su segundo ejemplo es más como:sin([[y],[y],..[y]])
MSeifert el
Una muy buena ilustración. Gracias por poner tanto esfuerzo.
natersoz
interpolated_grid = interpolated(xx, yy)- esto no funciona para mí, error:x and y should both be 1-D arrays
Nixt
4

meshgrid ayuda a crear una cuadrícula rectangular a partir de dos matrices 1-D de todos los pares de puntos de las dos matrices.

x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 2, 3, 4])

Ahora, si ha definido una función f (x, y) y desea aplicar esta función a todas las combinaciones posibles de puntos de las matrices 'x' e 'y', puede hacer esto:

f(*np.meshgrid(x, y))

Digamos, si su función solo produce el producto de dos elementos, entonces así es como se puede lograr un producto cartesiano, de manera eficiente para grandes matrices.

Referido desde aquí

Narasimhan
fuente
1

Idea básica

Dados los posibles valores de x xs, (piense en ellos como las marcas de graduación en el eje x de un gráfico) y los posibles valores de y ys, meshgridgenera el conjunto correspondiente de puntos de cuadrícula (x, y) --- análogos a set((x, y) for x in xs for y in yx). Por ejemplo, si xs=[1,2,3]y ys=[4,5,6], obtendríamos el conjunto de coordenadas {(1,4), (2,4), (3,4), (1,5), (2,5), (3,5), (1,6), (2,6), (3,6)}.

Forma del valor de retorno

Sin embargo, la representación que meshgriddevuelve es diferente de la expresión anterior de dos maneras:

Primero , meshgridestablece los puntos de la cuadrícula en una matriz 2d: las filas corresponden a diferentes valores de y, las columnas corresponden a diferentes valores de x --- como en list(list((x, y) for x in xs) for y in ys), lo que daría la siguiente matriz:

   [[(1,4), (2,4), (3,4)],
    [(1,5), (2,5), (3,5)],
    [(1,6), (2,6), (3,6)]]

En segundo lugar , meshgriddevuelve las coordenadas x e y por separado (es decir, en dos matrices 2d numpy diferentes):

   xcoords, ycoords = (
       array([[1, 2, 3],
              [1, 2, 3],
              [1, 2, 3]]),
       array([[4, 4, 4],
              [5, 5, 5],
              [6, 6, 6]]))
   # same thing using np.meshgrid:
   xcoords, ycoords = np.meshgrid([1,2,3], [4,5,6])
   # same thing without meshgrid:
   xcoords = np.array([xs] * len(ys)
   ycoords = np.array([ys] * len(xs)).T

Tenga en cuenta np.meshgridque también puede generar cuadrículas para dimensiones superiores. Dados xs, ys y zs, obtendría xcoords, ycoords, zcoords como matrices 3d. meshgridtambién admite el orden inverso de las dimensiones, así como una representación dispersa del resultado.

Aplicaciones

¿Por qué querríamos esta forma de salida?

Aplique una función en cada punto de una cuadrícula: una motivación es que los operadores binarios como (+, -, *, /, **) están sobrecargados para matrices numpy como operaciones de elementos. Esto significa que si tengo una función def f(x, y): return (x - y) ** 2que funciona en dos escalares, también puedo aplicarla en dos matrices numpy para obtener una matriz de resultados por elementos: por ejemplo, f(xcoords, ycoords)o f(*np.meshgrid(xs, ys))da lo siguiente en el ejemplo anterior:

array([[ 9,  4,  1],
       [16,  9,  4],
       [25, 16,  9]])

Producto externo de dimensiones superiores: No estoy seguro de qué tan eficiente es esto, pero usted puede conseguir productos de alta dimensión exterior de esta manera: np.prod(np.meshgrid([1,2,3], [1,2], [1,2,3,4]), axis=0).

Gráficos de contorno en matplotlib: Me encontré meshgridal investigar el trazado de gráficos de contorno con matplotlib para trazar límites de decisión . Para esto, genera una cuadrícula con meshgrid, evalúa la función en cada punto de la cuadrícula (por ejemplo, como se muestra arriba) y luego pasa los xcoords, ycoords y los valores f calculados (es decir, zcoords) en la función contourf.

usuario3780389
fuente