Quel est le but de meshgrid en Python / NumPy?

quelqu'un Peut m'expliquer quel est le but de meshgrid fonction Numpy? Je sais que ça crée une sorte de grille de coordonnées pour tracer, mais je ne vois pas l'avantage direct de ça.

j'étudie "Python Machine Learning" DE Sebastian Raschka, et il l'utilise pour tracer les frontières de décision. Voir Entrée 11 ici .

j'ai également essayé ce code à partir de la documentation officielle, mais, encore une fois, la sortie n'a pas vraiment de sens pour moi.

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)

s'il vous plaît, si possible, aussi me montrer beaucoup d'exemples du monde réel.

136
demandé sur Suever 2016-03-15 16:43:43

5 réponses

Le but de meshgrid est de créer une grille rectangulaire de sortir d'un tableau de valeurs x et un tableau de valeurs de y.

Ainsi, par exemple, si nous voulons créer une grille où nous avons un point à chaque valeur entière entre 0 et 4 dans les deux directions x et y. Pour créer une grille rectangulaire, nous avons besoin de chaque combinaison des points x et y .

ça va faire 25 points, non? Donc, si nous voulions créer un x et y tableau pour tous ces points, nous pourrait faire ce qui suit.

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

Ce résultat suivant x et y matrices, telles que le couplage de l'élément correspondant dans chaque matrice donne les coordonnées x et y d'un point dans la grille.

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

nous pouvons ensuite tracer ceux-ci pour vérifier qu'ils sont une grille:

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

enter image description here

évidemment, cela devient très fastidieux surtout pour les grandes gammes de x et y . Au lieu de cela, meshgrid peut réellement générer ceci pour nous: tout ce que nous devons spécifier sont les valeurs uniques x et y .

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

maintenant, quand nous appelons meshgrid , nous obtenons la sortie précédente automatiquement.

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

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

enter image description here

la Création de ces grilles rectangulaires est utile pour un certain nombre de tâches. Dans l'exemple que vous avez fourni dans votre post, c'est simplement une façon d'échantillonner une fonction ( sin(x**2 + y**2) / (x**2 + y**2) ) sur une plage de valeurs pour x et y .

parce que cette fonction a été échantillonnée sur une grille rectangulaire, la fonction peut maintenant être visualisée comme une"image".

enter image description here

en outre, le résultat peut maintenant être passé à des fonctions qui attendent des données sur la grille rectangulaire (i.e. contourf )

195
répondu Suever 2018-07-29 12:35:37

gracieuseté de Microsoft Excelle:

enter image description here

106
répondu Hai Phan 2017-03-03 13:27:27

supposons que vous ayez une fonction:

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

et vous voulez, par exemple, voir à quoi il ressemble dans la gamme de 0 à 2*pi. Comment le feriez-vous? Il y a np.meshgrid entre:

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

et un tel complot ressemblerait à:

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

enter image description here

Donc np.meshgrid est juste une commodité. En principe, la même chose pourrait être fait par:

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

mais là vous devez être conscient de vos dimensions (supposons que vous en ayez plus de deux ...) et le droit de radiodiffusion. np.meshgrid fait tout cela pour vous.

meshgrid vous permet également de supprimer les coordonnées avec les données si, par exemple, vous voulez faire une interpolation mais exclure certaines valeurs:

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

alors comment feriez-vous l'interpolation maintenant? Vous pouvez donner x et y à une fonction d'interpolation comme scipy.interpolate.interp2d donc vous avez besoin d'un moyen de savoir quelles coordonnées ont été supprimées:

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

et puis vous pouvez toujours interpoler avec le "droit" de coordonnées (essayer sans meshgrid et vous aurez beaucoup de code supplémentaire):

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

et le meshgrid original vous permet d'obtenir l'interpolation sur la grille d'origine à nouveau:

interpolated_grid = interpolated(xx, yy)

ce ne sont que quelques exemples où j'ai utilisé le meshgrid il pourrait y avoir beaucoup plus.

25
répondu MSeifert 2016-03-15 14:50:52

en fait, le but de np.meshgrid est déjà mentionné dans la documentation:

np.meshgrid

matrices de coordonnées de retour des vecteurs de coordonnées.

Faire de N-D de coordonner les tableaux pour vectorisé évaluations de N-D scalaire/vectorielle des champs de plus de N-D des grilles, donné à une dimension de coordonner les tableaux x1, x2,..., xn.

donc son but premier est de créer des matrices de coordonnées.

vous vous êtes probablement demandé:

Pourquoi devons-nous créer des matrices de coordonnées?

la raison pour laquelle vous avez besoin de matrices de coordonnées avec Python/NumPy est qu'il n'y a pas de relation directe entre les coordonnées et les valeurs, sauf lorsque vos coordonnées commencent par zéro et sont des entiers purement positifs. Ensuite, vous pouvez simplement utiliser les indices d'un tableau comme index. Toutefois, lorsque ce n'est pas le cas, vous avez en quelque sorte besoin de stocker des coordonnées à côté de vos données. C'est là que les grilles entrent en jeu.

supposons que vos données soient:

1  2  1
2  5  2
1  2  1

Cependant chaque valeur représente une région de 2 kilomètres de large horizontalement et 3 kilomètres verticalement. Supposons que votre origine soit le coin supérieur gauche et vous voulez des tableaux qui représentent la distance que vous pourriez utiliser:

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

h est:

0  2  4
0  2  4
0  2  4

et h:

0  0  0
3  3  3
6  6  6

donc si vous avez deux indices, disons x et y (c'est pourquoi la valeur de retour de meshgrid est habituellement xx ou xs au lieu de x dans ce cas j'ai choisi h pour horizontalement! ensuite, vous pouvez obtenir la coordonnée x du point, la coordonnée y du point et de la valeur à ce point en utilisant:

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

Cela rend beaucoup plus facile de garder la trace des coordonnées et (encore plus important) vous pouvez les passer à des fonctions qui ont besoin de connaître les coordonnées.

une explication un peu plus longue

Toutefois, np.meshgrid lui-même n'est pas souvent utilisé directement, souvent on utilise juste l'un des similaires objets np.mgrid ou np.ogrid . Ici np.mgrid représente le sparse=False et np.ogrid le sparse=True cas (je me réfère à la sparse argument np.meshgrid ). Notez qu'il existe une différence significative entre np.meshgrid et np.ogrid et np.mgrid : les deux premières valeurs retournées (s'il y en a deux ou plus) sont inversées. Souvent, cela n'a pas d'importance, mais vous devriez donner des noms de variables significatives en fonction du contexte. Par exemple dans le cas d'une grille 2D et matplotlib.pyplot.imshow il est permis de nommer le premier article retourné de np.meshgrid x et le second y alors qu'il est l'inverse pour np.mgrid et np.ogrid .

np.ogrid et réseaux épars

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

comme déjà dit la sortie est inversée par rapport à np.meshgrid , c'est pourquoi je l'ai déballé comme yy, xx au lieu 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]])

cela ressemble déjà à des coordonnées, en particulier le x et des lignes y pour les parcelles 2D.

visualisé:

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

enter image description here

np.mgrid 1519900920"
>>> 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]])

la même chose s'applique ici: la sortie est inversée par rapport à 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]])

contrairement à ogrid ces tableaux contiennent tous xx et yy coordonnées dans le -5 <= xx <= 5; -5 <= yy <= 5 grille.

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

enter image description here

fonctionnalité

ce n'est pas seulement limité à la 2D, ces fonctions fonctionnent pour des dimensions arbitraires (bien, il y a un nombre maximum d'arguments donnés à la fonction en Python et un nombre maximum de dimensions que NumPy permet):

>>> 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.

même si cela fonctionne aussi pour 1D il y a deux (beaucoup plus commun) fonctions de création de grille 1D:

outre l'argument start et stop il soutient également l'argument step (même les étapes complexes qui représentent le nombre d'étapes):

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

Applications

vous avez spécifiquement demandé sur le but et en fait ces grilles sont extrêmement utiles si vous avez besoin d'un système de coordonnées.

par exemple si vous avez une fonction NumPy qui calcule la distance en deux dimensions:

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

Et vous voulez connaître la distance de chaque point:

>>> 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 sortie serait identique si on passait dans une grille dense au lieu d'une grille ouverte. Num pys broadcasting rend cela possible!

visualisons le résultat:

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

enter image description here

et c'est aussi le moment où NumPys mgrid et ogrid deviennent très pratiques, parce qu'il vous permet de changer facilement la résolution de vos grilles:

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

enter image description here

Cependant, puisque imshow ne supporte pas x et "1519230920 entrées" on doit changer les tiques à la main. Il serait vraiment pratique si elle accepterait de la x et y coordonnées, droit?

Il est facile d'écrire des fonctions avec NumPy qui traitent naturellement avec des grilles. En outre, il existe plusieurs fonctions de NumPy, SciPy, MatPlotLib qu'attendez vous pour passer dans la grille.

j'aime les images donc, nous allons explorer 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)

enter image description here

Note la façon dont les coordonnées sont déjà correctement réglé! Ce ne serait pas le cas si vous venez de passer dans le density .

Ou pour donner un autre exemple amusant à l'aide de astropy modèles (cette fois, j'ai ne vous souciez pas beaucoup des coordonnées, je les utilise juste pour créer certains grille):

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)

enter image description here

bien que ce soit juste "pour les looks" plusieurs fonctions liées aux modèles fonctionnels et l'ajustement (par exemple scipy.interpolate.interp2d , scipy.interpolate.griddata même montrer des exemples en utilisant np.mgrid ) en Scipy, etc. exiger des grilles. La plupart d'entre eux fonctionnent avec des grilles ouvertes et les grilles denses, cependant certains ne fonctionnent qu'avec l'un d'eux.

15
répondu MSeifert 2018-03-22 22:27:08

meshgrid aide à créer une grille rectangulaire à partir de deux tableaux 1-D de toutes les paires de points des deux tableaux.

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

maintenant, si vous avez défini une fonction f (x, y) et que vous voulez appliquer cette fonction à toutes les combinaisons possibles de points des tableaux 'x' et 'y', alors vous pouvez faire ceci:

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

dire, si votre Fonction produit juste le produit de deux éléments, alors c'est comment un produit cartésien peut être atteint, efficace pour de grands tableaux.

Visée de ici

0
répondu Narasimhan 2018-05-11 10:32:01