web-dev-qa-db-fra.com

Pourquoi pyplot.contour () exige-t-il que Z soit un tableau 2D?

La fonction matplotlib.pyplot.contour() accepte 3 tableaux d'entrée X, Y et Z.
Les tableaux X et Y spécifient les coordonnées x et y des points, tandis que Z spécifie la valeur correspondante de la fonction d'intérêt évaluée aux points.

Je comprends que np.meshgrid() facilite la production de tableaux qui servent d’arguments à contour():

X = np.arange(0,5,0.01)
Y = np.arange(0,3,0.01)

X_grid, Y_grid = np.meshgrid(X,Y)
Z_grid = X_grid**2 + Y_grid**2

plt.contour(X_grid, Y_grid, Z_grid)  # Works fine

Cela fonctionne bien. Et cela fonctionne bien aussi:

plt.contour(X, Y, Z_grid)  # Works fine too

Cependant, pourquoi la Z entréerequiredest-elle un tableau 2D? 

Pourquoi certaines choses comme celles-ci sont-elles interdites, même si elles spécifient que les mêmes données sont alignées correctement?

plt.contour(X_grid.ravel(), Y_grid.ravel(), Z_grid.ravel())  # Disallowed

Aussi, quelles sont les sémantiques lorsque seulement Z est spécifié (sans les X et Y correspondants)?

9
dhrumeel

En regardant la documentation de contour , on s'aperçoit qu'il existe plusieurs façons d'appeler cette fonction, par exemple: contour(Z) ou contour(X,Y,Z). Vous constaterez donc que la présence de valeurs X ou Y n'est pas nécessaire.

Cependant, pour tracer un contour, la grille sous-jacente doit être connue de la fonction. La variable contour de Matplotlib est basée sur une grille rectangulaire. Mais même dans ce cas, autoriser contour(z), avec z étant un tableau 1D, rendrait impossible de savoir comment le champ devrait être tracé. Dans le cas de contour(Z)Z est un tableau 2D, sa forme définit sans ambiguïté la grille du tracé. 

Une fois que cette grille est connue, peu importe que les tableaux optionnels X et Y soient aplatis ou non; ce qui est en fait ce que la documentation nous dit:

X et Y doivent tous deux être 2-D avec la même forme que Z ou doivent être tous les deux 1-D tels que len (X) représente le nombre de colonnes dans Z et len ​​(Y) représente le nombre de lignes dans Z.

Il est également assez évident que quelque chose comme plt.contour(X_grid.ravel(), Y_grid.ravel(), Z_grid.ravel()) ne peut pas produire de tracé de contour, car toutes les informations relatives à la forme de la grille sont perdues et la fonction de contour ne saurait en aucun cas savoir interpréter les données. Par exemple. Si len(Z_grid.ravel()) == 12, la forme de la grille sous-jacente pourrait être un des (1,12), (2,6), (3,4), (4,3), (6,2), (12,1).

Une solution possible serait bien sûr de permettre l'utilisation de tableaux 1D et d'introduire un argument shape, tel que plt.contour(x,y,z, shape=(6,2)). Ce n'est cependant pas le cas, vous devez donc vivre avec le fait que Z doit être 2D.

Cependant, si vous cherchez un moyen d’obtenir un tracé graphique avec des tableaux aplatis (défilés), cela est possible avec plt.tricontour() .

plt.tricontour(X_grid.ravel(), Y_grid.ravel(), Z_grid.ravel()) 

Ici, une grille triangulaire sera produite en interne en utilisant une triangulation de Delaunay. Par conséquent, même des points complètement aléatoires produiront un résultat de Nice, comme on peut le voir sur l'image suivante, où il est comparé aux mêmes points aléatoires donnés à contour.

 enter image description here

(Voici le code pour produire cette image )

5

La raison pour laquelle X et Y sont 2D est la suivante: . Z correspond à chaque coordonnée (x, y) dans le système d'axes d'une "profondeur" correspondante pour créer un tracé 3D avec des coordonnées x, y et z.

Supposons maintenant que nous souhaitons pointer sur un point quelconque du système d'axes . Nous pouvons le faire en fournissant les coordonnées x et y (x, y) pour ce point.Par exemple (0,0). Considérons maintenant la "ligne" avec la valeur x 1. Sur cette ligne, il y a un certain nombre de valeurs y et qui ressemblent à ceci:

 enter image description here

Si nous traçons ces lignes pour toutes les valeurs x et y, nous obtiendrons qch. comme:

 enter image description here

Comme vous pouvez le constater, nous avons une annotation 2D composée de tableaux 2 2D, une pour les valeurs x ayant la forme suivante:

1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
#--> Two dimensional x values array

et un pour les valeurs y qui a la forme:

10 10 10 10 10 10 10 10 10 10
9 9 9 9 9 9 9 9 9 9 
8 8 8 8 8 8 8 8 8 8
...
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0
#--> Two dimensional y values array

Ces deux ensembles fournissent les coordonnées (x, y) de chaque point du système de coordonnées. Maintenant, nous pouvons tracer pour chaque point la "profondeur" signifie la valeur Z (coordonnée z) . Maintenant, il est également évident que la variable Z doit être 2 dimensions avec la forme (len (x), len (y)) sinon, il ne peut pas fournir de valeur pour tous les points.

Ce comportement peut être réalisé en fournissant des tableaux 2D x, y et z à la fonction OU: fournissez des tableaux 1D x et y à la fonction et la fonction crée en interne le maillage 2D à partir des valeurs x et y avec smth. comme X, Y = np.meshgrid (x, y) mais néanmoins z doit être bidimensionnel.

0
2Obe

Permettez-moi de vous expliquer de manière simple, car je pensais que Z ne devrait pas également être en 2D. contourf() a besoin de X et Y pour construire son propre espace, et la relation Z (X, Y) pour construire un espace complet, plutôt que d'utiliser simplement plusieurs points avec des informations 1D X, Y, Z.

0
Wey Shi