Je veux dessiner le graphique comme l'image ci-dessous. Son axe x est l'ordre des points de données, par ex. de 1 à 7. L'axe des y est l'échelle de 0 à 25. Si je veux dessiner un triangle, par exemple, avec ses données (1,22,20), alors '1' donne l'ordre parmi tous les points de données (triangles différents), le triangle doit être dessiné le plus à gauche; "22,20" donne la "pointe inférieure" du triangle le long de l'axe y.
Est-ce que quelqu'un sait comment dessiner un tel triangle avec un nombre multiple dans un graphique en utilisant le package python matplotlib?
3 Réponses :
Lisez ce message et ce post sur le dessin de polygones avec matplotlib.
EDIT1: Je viens de voir la réponse de @ Poolka. C'était aussi ma façon de procéder, mais notez que dans l'un des liens ci-dessus, il est indiqué que l'ajout de polygones simples ( p = pat.Polygon ([[x1, y1], [x2, y2], [ x3, y3]); ax.add_patch (p)
) à la figure peut devenir très lent, et donc les collections sont préférées.
EDIT 2: Voir aussi La réponse de TheImportanceOfBeingErnest pour une version plus élaborée de ce concept. Avec cet extrait de code, il devrait vous permettre de démarrer:
import numpy as np import matplotlib import matplotlib.pyplot as plt import matplotlib.patches as pat # Patches like pat.Polygon() from matplotlib.collections import PolyCollection # Collections of patches test = ((1, 22, 20), (2, 21, 19.5), (3, 18, 20)) # Test data triangles = [] fig, ax = plt.subplots(1, 1) for t in test: xmid = t[0] # Middle x-coord xleft = t[0] - 0.5 xright = t[0] + 0.5 # Use fixed width of 0.5 y1 = t[1] # y-coords y2 = t[2] coordinates = [[xleft, y1], [xright, y1], [xmid, y2]] print(coordinates) triangles.append(coordinates) # Append to collection z = np.random.random(len(triangles)) collec = PolyCollection(triangles, array=z, cmap=matplotlib.cm.viridis) ax.add_collection(collec) # Plot polygon collection ax.autoscale_view() plt.show()
Il devrait toujours être coordonnées = [[xleft, y1], [xright, y1], [xmid, y2]]
, indépendamment de l'ordre !!
J'ai supprimé cette ligne superflue maintenant. Notez que vos deux liens ont la même cible. Toujours voté.
Jésus, je suppose que j'étais un peu distrait, haha. Je vais mettre à jour le deuxième lien.
Prenons l'exemple simple suivant:
import matplotlib.pyplot as plt # data data = [[1, 22, 20], [3, 20, 25]] plt.figure() for val in data: # coordinates dy = val[1] - val[2] dx = abs(dy) / 2 x0 = val[0] y0 = val[1] # drawing triangle = plt.Polygon([[x0, y0], [x0 - dx, y0 + dy], [x0 + dx, y0 + dy]]) plt.gca().add_patch(triangle) # misc plt.grid() plt.axis('square') # these 2 lines are needed because patches in matplotlib do not adjust axes limits automatically, another approach is to add some data to the figure with plot, scatter, etc. plt.xlim([-20, 20]) plt.ylim([0, 40])
Utilisation d'une PolyCollection
( comme indiqué dans la réponse de @ cripcate ) est avantageux dans ce cas. Une version plus condensée utilisant un seul tableau numpy pourrait ressembler à ceci:
import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import PolyCollection def triangle_collection(d, ax=None, width=0.4, **kwargs): ax = ax or plt.gca() verts = np.c_[d[:,0]-width/2, d[:,1], d[:,0]+width/2, d[:,1], d[:,0], d[:,2]].reshape(len(d),3,2) c = PolyCollection(verts, **kwargs) ax.add_collection(c) ax.autoscale() return c data = np.array([(1,22,20), (2,21,19.5), (3,18,20), (4,17,19), (5,15,17), (6,11,8.5), (7,14,12)]) fig, ax = plt.subplots() fig.subplots_adjust(left=0.3, right=0.7) triangle_collection(data, facecolors=plt.cm.tab10(np.arange(len(data)))) plt.show()