Quel est le but de meshgrid en Python / NumPy?

303

Quelqu'un peut-il m'expliquer à quoi sert la meshgridfonction dans Numpy? Je sais que cela crée une sorte de grille de coordonnées pour le traçage, mais je ne peux pas vraiment en voir l'avantage direct.

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, montrez-moi aussi beaucoup d'exemples concrets.

HonzaB
la source

Réponses:

391

Le but de meshgridest de créer une grille rectangulaire à partir d'un tableau de valeurs x et d'un tableau de valeurs 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 directions x et y. Pour créer une grille rectangulaire, nous avons besoin de chaque combinaison des points xet y.

Cela va être de 25 points, non? Donc, si nous voulions créer un tableau x et y pour tous ces points, nous pourrions 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

Il en résulterait ce qui suit xet des ymatrices, de sorte que l'appariement 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')

entrez la description de l'image ici

Évidemment, cela devient très fastidieux, en particulier pour les grandes gammes de xet y. Au lieu de cela, meshgridpeut effectivement générer ce pour nous: tout ce que nous devons préciser sont les uniques xet les yvaleurs.

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

Maintenant, lorsque nous appelons meshgrid, nous obtenons automatiquement la sortie précédente.

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

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

entrez la description de l'image ici

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 article, c'est simplement un moyen d'échantillonner une fonction ( sin(x**2 + y**2) / (x**2 + y**2)) sur une plage de valeurs pour xet y.

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

entrez la description de l'image ici

De plus, le résultat peut maintenant être transmis aux fonctions qui attendent des données sur une grille rectangulaire (c.-à-d. contourf)

Suever
la source
10
Vous n'avez pas expliqué les valeurs de retour xxet yy. La partie mystérieuse pour moi était pourquoi elle renvoie cette paire de résultats, et à quoi ils ressemblent. La réponse de Hai Phan est pratique pour cela. Je suppose que cela fait cela pour plus de commodité, car l'intrigue veut deux paramètres comme ça.
nealmcb
2
Je ne sais pas - c'est pourquoi je recherche ces informations;) Je ne dis donc pas qu'elles devraient renvoyer quelque chose de différent. Je donne juste ma meilleure estimation d'une information manquante pour ceux qui viennent de lire la réponse acceptée. Et si vous le souhaitez, je suggère que votre réponse (qui est déjà très agréable - merci!) Serait un peu plus complète si vous expliquiez les valeurs de retour (comme l'a fait Hai), pour ceux d'entre nous qui sont encore perplexes.
nealmcb
1
Pour mieux comprendre les valeurs de xx et yy, considérez l'affirmation selon laquelle le code suivant vous donne le même résultat que np.meshgrid:xx = [xvalues for y in yvalues] yy = [[y for x in xvalues] for y in yvalues]
Matt Kleinsmith
1
Cette réponse est déroutante - n'est-ce pas votre première illustration de xet en yarrière? Lorsque vous le faites xx, yy = np.meshgrid(np.arange(4), np.arange(4)), c'est l'inverse de ce que vous avez xet ydans la première partie de la réponse. Il correspond à l'ordre des sorties pour mgrid, mais pas au meshgrid. Le xxdevrait augmenter dans la direction x, mais le vôtre augmente dans la direction y.
Scott Staniewicz
1
@ScottStaniewicz Merci d'avoir souligné que notre, maintenant sûr de la façon dont j'ai foiré celui-là ... Mis à jour!
Suever
250

Gracieuseté de Microsoft Excel: 

entrez la description de l'image ici

Salsepareille
la source
6
Agréable. Fwiw, si vous voulez un tableau 2 x 12 des paires au milieu:XYpairs = np.vstack([ XX.reshape(-1), YY.reshape(-1) ])
denis
5
et si vous voulez un tableau 12 x 2 des paires au milieu:XYpairs = np.dstack([XX, YY]).reshape(-1, 2)
barlaensdoonn
2
Bonne réponse. Le but de meshgrid est de créer une grille en utilisant les coordonnées de chaque dim.
Bon garçon
1
Ce que je trouve un peu étrange, c'est que les valeurs x et y sont retournées séparément au lieu d'être déjà combinées dans un tableau. Si je les veux dans un tableau, je dois faire:np.vstack([XX.ravel(), YY.ravel()]).T
user3629892
66

En fait, le but de np.meshgridest déjà mentionné dans la documentation:

np.meshgrid

Renvoie les matrices de coordonnées des vecteurs de coordonnées.

Faire des tableaux de coordonnées ND pour des évaluations vectorisées de champs scalaires / vectoriels ND sur des grilles ND, étant donné les tableaux de coordonnées unidimensionnels x1, x2, ..., xn.

Son objectif principal est donc de créer une matrice 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. Cependant, lorsque ce n'est pas le cas, vous devez en quelque sorte stocker les coordonnées à côté de vos données. C'est là qu'interviennent les grilles.

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 de 3 kilomètres verticalement. Supposons que votre origine soit le coin supérieur gauche et que vous vouliez 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)

où v est:

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

et h:

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

Donc, si vous avez deux indices, disons xet y(c'est pourquoi la valeur de retour de meshgridest généralement xxou xsau lieu de xdans ce cas j'ai choisi hhorizontalement!), Alors vous pouvez obtenir la coordonnée x du point, la coordonnée y du point et le valeur à ce point en utilisant:

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

Cela facilite grandement le suivi des coordonnées et (plus important encore) vous pouvez les transmettre à des fonctions qui ont besoin de connaître les coordonnées.

Une explication un peu plus longue

Cependant, np.meshgridlui-même n'est pas souvent utilisé directement, la plupart du temps, on utilise simplement l'un des objets similairesnp.mgrid ou np.ogrid. Ici np.mgridreprésente le sparse=Falseet np.ogridle sparse=Truecas (je me réfère à l' sparseargument de np.meshgrid). Notez qu'il existe une différence significative entre np.meshgridet np.ogridet np.mgrid: Les deux premières valeurs renvoyées (s'il y en a deux ou plus) sont inversées. Souvent, cela n'a pas d'importance, mais vous devez donner des noms de variables significatifs en fonction du contexte.

Par exemple, dans le cas d'une grille 2D et matplotlib.pyplot.imshowil est logique de nommer le premier élément retourné de np.meshgrid xet le second yalors que c'est l'inverse pour np.mgridet np.ogrid.

np.ogrid et grilles clairsemées

>>> 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écompressée au yy, xxlieu 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 les lignes x et y pour les tracés 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")

entrez la description de l'image ici

np.mgrid et grilles denses / étoffées

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

Il en va de même 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 à ogridces tableaux contiennent tous xx et yycoordonné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")

entrez la description de l'image ici

Fonctionnalité

Ce n'est pas seulement limité à la 2D, ces fonctions fonctionnent pour des dimensions arbitraires (enfin, il y a un nombre maximum d'arguments donnés pour fonctionner 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 ceux-ci fonctionnent également pour 1D, il existe deux fonctions de création de grille 1D (beaucoup plus courantes):

Outre l' argument startet stop, il prend également en charge l' stepargument (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é à propos de l'objectif 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 l'on passait dans une grille dense au lieu d'une grille ouverte. La diffusion NumPys 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()

entrez la description de l'image ici

Et cela est aussi quand NumPys mgridet ogriddeviennent très pratique car 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

entrez la description de l'image ici

Toutefois, étant donné que imshowne prend pas en charge xet les yentrées on doit changer les tiques à la main. Ce serait vraiment pratique s'il acceptait les coordonnées xet y, n'est-ce pas?

Il est facile d'écrire des fonctions avec NumPy qui traitent naturellement des grilles. De plus, il existe plusieurs fonctions dans NumPy, SciPy, matplotlib qui s'attendent à ce que vous passiez dans la grille.

J'aime les images alors explorons 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)

entrez la description de l'image ici

Notez comment les coordonnées sont déjà correctement définies! Ce ne serait pas le cas si vous veniez de passer le density.

Ou pour donner un autre exemple amusant en utilisant des modèles d'astropie (cette fois, je ne me soucie pas beaucoup des coordonnées, je les utilise juste pour créer une 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)
    

entrez la description de l'image ici

Bien que ce soit juste "pour l'apparence", plusieurs fonctions liées aux modèles fonctionnels et à l'ajustement (par exemple scipy.interpolate.interp2d, scipy.interpolate.griddatamême montrer des exemples d'utilisation np.mgrid) dans Scipy, etc. nécessitent des grilles. La plupart d'entre eux fonctionnent avec des grilles ouvertes et des grilles denses, mais certains ne fonctionnent qu'avec l'une d'entre elles.

MSeifert
la source
Je veux juste dire un énorme merci pour cette réponse extrêmement détaillée. Cela a fait ma journée.
Jlanger
Quelle belle façon de répondre à une question ... si détaillée. Merci
Bipin
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)- depuis ses 2 km horizontaux et 3 km verticaux, la première plage ne doit-elle pas être multipliée par 2 et la seconde par 3?
Nixt
@Nixt Malheureusement, ce n'est pas aussi simple que cela. Je devrais peut-être vérifier à nouveau cette partie de la réponse. C'est un compromis entre l'affichage transposé de la matrice et l'indexation inversée - normalement, vous vous attendez à ce que le premier index soit horizontal et le deuxième vertical, mais ensuite l'affichage serait transposé. Cependant, il s'agit principalement d'un détail qui, espérons-le, n'invalide pas l'essence de la réponse qui vise à illustrer la raison des grilles. Mais je vais essayer de réviser cela à une date ultérieure.
MSeifert
36

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 plage de 0 à 2 * pi. Comment feriez-vous? Il y a np.meshgrid:

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

entrez la description de l'image ici

C'est donc np.meshgridjuste une commodité. En principe, la même chose pourrait être faite 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 de la bonne diffusion. np.meshgridfait tout cela pour vous.

Le meshgrid vous permet également de supprimer les coordonnées avec les données si vous voulez, par exemple, 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 xet yà une fonction d'interpolation comme scipy.interpolate.interp2dvous avez donc besoin d'un moyen de savoir quelles coordonnées ont été supprimées:

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

et ensuite vous pouvez toujours interpoler avec les "bonnes" coordonnées (essayez-le sans le meshgrid et vous aurez beaucoup de code supplémentaire):

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

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

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

Ce ne sont que quelques exemples où j'ai utilisé le meshgridil pourrait y en avoir beaucoup plus.

MSeifert
la source
1
Merci pour votre réponse! Le moment le plus déroutant pour moi est retourné des valeurs xx, yy. Il était difficile de comprendre ce qu'ils sont et pourquoi nous les utilisons pour calculer la fonction. On dirait que je l'ai. Nous voulons calculer une fonction basée sur des coordonnées. Nous pouvons écrire quelque chose comme ceci: for x=1:10: for y=1:10: z[x,y]=sin(x)+sin(y)Au lieu de cela, nous calculons zd'une manière différente z=sin([x,x,...,x]) + sin([y,y,..y]). Corrigez-moi si je me trompe!
Alena Kastsiukavets
Ce n'est pas un pseudo-code 100% correct, mais j'espère que vous voyez mon point)
Alena Kastsiukavets
En fait, vous avez toujours besoin de la double boucle (votre premier code). Mais il existe différentes manières de l'archiver avec numpy: maillage ou diffusion. Si vous ne jetez pas de points (voir la dernière partie de ma réponse), les deux sont en fait fonctionnellement équivalents. La diffusion n'est qu'une boucle implicite à travers la dimension à diffuser. Notez que j'ai utilisé [:,None]et [None, :]pour inclure des dimensions supplémentaires afin que le résultat diffuse correctement. Votre deuxième exemple ressemble plus à:sin([[y],[y],..[y]])
MSeifert
Une très belle illustration. Merci d'avoir fait tant d'efforts.
natersoz
interpolated_grid = interpolated(xx, yy)- cela ne fonctionne pas pour moi, erreur:x and y should both be 1-D arrays
Nixt
4

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 le faire:

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

Disons que si votre fonction produit simplement le produit de deux éléments, c'est ainsi qu'un produit cartésien peut être réalisé, efficacement pour les grands tableaux.

Référé d' ici

Narasimhan
la source
1

Idée basique

Compte tenu des valeurs possibles de x, xs, (les considérer comme les graduations sur l'axe des x d'une parcelle) et les valeurs y possibles, ys, meshgridgénère des points de grille ensemble de (x, y) correspondant --- analogues à set((x, y) for x in xs for y in yx). Par exemple, si xs=[1,2,3]et ys=[4,5,6], nous obtiendrions l'ensemble des coordonnées {(1,4), (2,4), (3,4), (1,5), (2,5), (3,5), (1,6), (2,6), (3,6)}.

Forme de la valeur de retour

Cependant, la représentation meshgridrenvoyée diffère de l'expression ci-dessus de deux manières:

Tout d'abord , meshgridétablit les points de la grille dans un tableau 2d: les lignes correspondent à différentes valeurs y, les colonnes correspondent à différentes valeurs x --- comme dans list(list((x, y) for x in xs) for y in ys), ce qui donnerait le tableau suivant:

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

Deuxièmement , meshgridrenvoie les coordonnées x et y séparément (c'est-à-dire dans deux tableaux numpy 2d différents):

   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

Remarque, np.meshgridpeut également générer des grilles pour des dimensions supérieures. Étant donné xs, ys et zs, vous récupérez les xcoords, ycoords, zcoords sous forme de tableaux 3D. meshgridprend également en charge l'ordre inverse des dimensions ainsi qu'une représentation clairsemée du résultat.

Applications

Pourquoi voudrions-nous cette forme de sortie?

Appliquer une fonction à chaque point d'une grille: Une motivation est que les opérateurs binaires comme (+, -, *, /, **) sont surchargés pour les tableaux numpy en tant qu'opérations élément par élément. Cela signifie que si j'ai une fonction def f(x, y): return (x - y) ** 2qui fonctionne sur deux scalaires, je peux également l'appliquer sur deux tableaux numpy pour obtenir un tableau de résultats élément par élément: par exemple f(xcoords, ycoords)ou f(*np.meshgrid(xs, ys))donne ce qui suit dans l'exemple ci-dessus:

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

Produit extérieur supérieur dimensions: Je ne sais pas comment cela est efficace, mais vous pouvez obtenir des produits extérieurs de grande dimension ainsi: np.prod(np.meshgrid([1,2,3], [1,2], [1,2,3,4]), axis=0).

Tracés de contour dans matplotlib: Je suis tombé sur une meshgridrecherche de tracés de contour avec matplotlib pour tracer les limites de décision . Pour cela, vous générez une grille avec meshgrid, évaluez la fonction à chaque point de grille (par exemple, comme indiqué ci-dessus), puis passez les xcoords, ycoords et les valeurs f calculées (c'est-à-dire zcoords) dans la fonction contourf.

user3780389
la source