tracer un cercle avec pyplot


158

étonnamment, je n'ai pas trouvé de description simple sur la façon de dessiner un cercle avec matplotlib.pyplot (s'il vous plaît pas de pylab) en prenant comme centre d'entrée (x, y) et rayon r. J'ai essayé quelques variantes de ceci:

import matplotlib.pyplot as plt
circle=plt.Circle((0,0),2)
# here must be something like circle.plot() or not?
plt.show()

... mais cela ne fonctionnait toujours pas.


Je suis sûr que c'est possible de le faire, mais matplotlib vise principalement à tracer (c'est-à-dire voici quelques données, mettez-les sur un graphique), pas à dessiner, donc ce n'est peut-être pas tout à fait simple.
Thomas K

Le rayon des points de nuage de points est de plus en plus utilisé pour visualiser les données. Les graphiques Google les appellent des «graphiques à bulles». Gapminder.org est un bon exemple. C'est complote, pas de dessin. J'ai cherché dans le repo matplotlib github "bulle" et "rayon de dispersion" en vain, donc je ne pense pas que ce soit sur la liste des choses à faire en ce qui concerne l'ajout d'une fonctionnalité.
Bennett Brown

1
plt.scatter () prend un argument de taille. Vous pouvez transmettre des listes pour les coordonnées x et y des cercles, les rayons des cercles et les couleurs des cercles. matplotlib.org/1.3.1/api/… . Mon erreur plus tôt, en pensant qu'une telle fonctionnalité n'était pas déjà dans matplotlib.
Bennett Brown

3
Juste pour mentionner: plt.Circle(..)dirige vers matplotlib.patches.Circle(). Donc, une solution sans pyplot serait circle = matplotlib.patches.Circle(..); axes.add_artist(circle).
ImportanceOfBeingErnest

Réponses:


203

Vous devez l'ajouter à un axe. A Circleest une sous-classe de an Artistet an axesa une add_artistméthode.

Voici un exemple de cette opération:

import matplotlib.pyplot as plt

circle1 = plt.Circle((0, 0), 0.2, color='r')
circle2 = plt.Circle((0.5, 0.5), 0.2, color='blue')
circle3 = plt.Circle((1, 1), 0.2, color='g', clip_on=False)

fig, ax = plt.subplots() # note we must use plt.subplots, not plt.subplot
# (or if you have an existing figure)
# fig = plt.gcf()
# ax = fig.gca()

ax.add_artist(circle1)
ax.add_artist(circle2)
ax.add_artist(circle3)

fig.savefig('plotcircles.png')

Cela donne la figure suivante:

Le premier cercle est à l'origine, mais par défaut clip_onest True, de sorte que le cercle est clipsé quand jamais il va au - delà du axes. Le troisième cercle (vert) montre ce qui se passe lorsque vous ne coupez pas le fichier Artist. Il s'étend au-delà des axes (mais pas au-delà de la figure, c'est-à-dire que la taille de la figure n'est pas automatiquement ajustée pour tracer tous vos artistes).

Les unités pour x, y et rayon correspondent aux unités de données par défaut. Dans ce cas, je n'ai rien tracé sur mes axes ( fig.gca()retourne les axes courants), et comme les limites n'ont jamais été définies, elles sont par défaut une plage x et y de 0 à 1.

Voici une suite de l'exemple, montrant l'importance des unités:

circle1 = plt.Circle((0, 0), 2, color='r')
# now make a circle with no fill, which is good for hi-lighting key results
circle2 = plt.Circle((5, 5), 0.5, color='b', fill=False)
circle3 = plt.Circle((10, 10), 2, color='g', clip_on=False)

ax = plt.gca()
ax.cla() # clear things for fresh plot

# change default range so that new circles will work
ax.set_xlim((0, 10))
ax.set_ylim((0, 10))
# some data
ax.plot(range(11), 'o', color='black')
# key data point that we are encircling
ax.plot((5), (5), 'o', color='y')

ax.add_artist(circle1)
ax.add_artist(circle2)
ax.add_artist(circle3)
fig.savefig('plotcircles2.png')

ce qui se traduit par:

Vous pouvez voir comment j'ai défini le remplissage du 2ème cercle sur False, ce qui est utile pour encercler les résultats clés (comme mon point de données jaune).


4
J'aime cette réponse parce que vous «dessinez» un cercle plutôt que de tracer. Bien que comploter aurait été aussi mon premier instinct.
samb8s

7
Pour votre information: il semble que la classe Circle est passée de matplotlib.pyplot à matplotlib.patches depuis que cette réponse a été écrite.
pavon

6
Mais mais mais les cercles sont ovales!
rubenvb

1
@rubenvb voir mon autre réponse: stackoverflow.com/questions/9230389/…
Yann

3
@pavon For me matplotlib.pyplot.Circle == matplotlib.patches.Circleévalue à True, donc ce sont probablement des alias.
Evgeni Sergeev

66
import matplotlib.pyplot as plt
circle1=plt.Circle((0,0),.2,color='r')
plt.gcf().gca().add_artist(circle1)

Une version condensée rapide de la réponse acceptée, pour brancher rapidement un cercle dans une parcelle existante. Reportez-vous à la réponse acceptée et aux autres réponses pour comprendre les détails.

Au fait:

  • gcf() signifie obtenir la figure actuelle
  • gca() signifie Obtenir l'axe actuel

4
Parfait! exactement ce que j'avais besoin de voir maintenant. dir(fig)me montre plus de 30 méthodes «get», mais gcan'a pas d' get_current_axisalias. Ces types de réponses fyi sont merveilleux.
uhoh

6
vous pouvez réellement faire à la plt.gca()place deplt.gcf().gca()
Andre Holzner

38

Si vous souhaitez tracer un ensemble de cercles, vous voudrez peut-être voir cet article ou cet essentiel (un peu plus récent). Le message proposait une fonction nommée circles.

La fonction circlesfonctionne comme scatter, mais les tailles des cercles tracés sont en unité de données.

Voici un exemple:

from pylab import *
figure(figsize=(8,8))
ax=subplot(aspect='equal')

#plot one circle (the biggest one on bottom-right)
circles(1, 0, 0.5, 'r', alpha=0.2, lw=5, edgecolor='b', transform=ax.transAxes)

#plot a set of circles (circles in diagonal)
a=arange(11)
out = circles(a, a, a*0.2, c=a, alpha=0.5, edgecolor='none')
colorbar(out)

xlim(0,10)
ylim(0,10)

entrez la description de l'image ici


Que fait transform=ax.transAxes-on?
Lee

3
@Lee C'est pour le cercle dans le coin inférieur droit, transformez les données en coordonnées des axes, c'est-à-dire que (1,1) signifie le coin supérieur droit en axes, (1,0) signifie le coin inférieur droit, etc.
Syrtis Major

4
Cela devrait faire partie de matplotlib.
JustAC0der

Cela peut-il être utilisé avec mplleaflet? Dans l'affirmative, pourriez-vous donner un exemple, s'il vous plaît?
François M.

@fmalaussena Comme cet extrait de code est pur matplotlib, je suppose qu'il devrait être compatible avec mplleafletbien que je n'ai jamais essayé.
Syrtis Major

21
#!/usr/bin/python
import matplotlib.pyplot as plt
import numpy as np

def xy(r,phi):
  return r*np.cos(phi), r*np.sin(phi)

fig = plt.figure()
ax = fig.add_subplot(111,aspect='equal')  

phis=np.arange(0,6.28,0.01)
r =1.
ax.plot( *xy(r,phis), c='r',ls='-' )
plt.show()

Ou, si vous préférez, regardez le paths, http://matplotlib.sourceforge.net/users/path_tutorial.html


2
Équation trignométrique d'un cercle et degress 0 tp 360, ce qui se traduit par 0 à 6,28319 radians mathopenref.com/coordparamcircle.html
Alex Punnen

19

Si vous souhaitez que le "cercle" conserve un rapport hauteur / largeur visuel de 1, quelles que soient les coordonnées des données, vous pouvez utiliser la méthode scatter (). http://matplotlib.org/1.3.1/api/pyplot_api.html#matplotlib.pyplot.scatter

import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [10, 20, 30, 40, 50]
r = [100, 80, 60, 40, 20] # in points, not data units
fig, ax = plt.subplots(1, 1)
ax.scatter(x, y, s=r)
fig.show()

L'image est un nuage de points.  Cinq cercles le long de la ligne y = 10x ont des rayons décroissants de bas à gauche en haut à droite.  Bien que le graphique soit de forme carrée, l'axe des y a 10 fois la plage de l'axe des x.  Même ainsi, le rapport hauteur / largeur des cercles est de 1 à l'écran.


11

Étendre la réponse acceptée pour un cas d'utilisation commun. En particulier:

  1. Affichez les cercles à un rapport hauteur / largeur naturel.

  2. Étendez automatiquement les limites des axes pour inclure les cercles nouvellement tracés.

Exemple autonome:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.add_patch(plt.Circle((0, 0), 0.2, color='r', alpha=0.5))
ax.add_patch(plt.Circle((1, 1), 0.5, color='#00ffff', alpha=0.5))
ax.add_artist(plt.Circle((1, 0), 0.5, color='#000033', alpha=0.5))

#Use adjustable='box-forced' to make the plot area square-shaped as well.
ax.set_aspect('equal', adjustable='datalim')
ax.plot()   #Causes an autoscale update.
plt.show()

Notez la différence entre ax.add_patch(..)et ax.add_artist(..): des deux, seul le premier fait que les machines d'autoscaling prennent en compte le cercle (référence: discussion ), donc après avoir exécuté le code ci-dessus, nous obtenons:

add_patch (..) vs add_artist (..)

Voir aussi: set_aspect(..)documentation .


En python3, vous devez supprimer fig, ax = plt.subplots(), sinon vous aurez deux fenêtres (l'une est vide).
albus_c

1

Je vois des parcelles avec l'utilisation de (.circle) mais en fonction de ce que vous voudrez peut-être faire, vous pouvez également essayer ceci:

import matplotlib.pyplot as plt
import numpy as np

x = list(range(1,6))
y = list(range(10, 20, 2))

print(x, y)

for i, data in enumerate(zip(x,y)):
    j, k = data
    plt.scatter(j,k, marker = "o", s = ((i+1)**4)*50, alpha = 0.3)

Tracé de cercle concentrique simple utilisant des points de progression linéaire

centers = np.array([[5,18], [3,14], [7,6]])
m, n = make_blobs(n_samples=20, centers=[[5,18], [3,14], [7,6]], n_features=2, 
cluster_std = 0.4)
colors = ['g', 'b', 'r', 'm']

plt.figure(num=None, figsize=(7,6), facecolor='w', edgecolor='k')
plt.scatter(m[:,0], m[:,1])

for i in range(len(centers)):

    plt.scatter(centers[i,0], centers[i,1], color = colors[i], marker = 'o', s = 13000, alpha = 0.2)
    plt.scatter(centers[i,0], centers[i,1], color = 'k', marker = 'x', s = 50)

plt.savefig('plot.png')

Points encerclés d'un problème de classification.


0

Bonjour, j'ai écrit un code pour dessiner un cercle. Cela aidera à dessiner toutes sortes de cercles. L'image montre le cercle avec le rayon 1 et le centre à 0,0 Le centre et le rayon peuvent être modifiés de n'importe quel choix.

## Draw a circle with center and radius defined
## Also enable the coordinate axes
import matplotlib.pyplot as plt
import numpy as np
# Define limits of coordinate system
x1 = -1.5
x2 = 1.5
y1 = -1.5
y2 = 1.5

circle1 = plt.Circle((0,0),1, color = 'k', fill = False, clip_on = False)
fig, ax = plt.subplots()
ax.add_artist(circle1)
plt.axis("equal")
ax.spines['left'].set_position('zero')
ax.spines['bottom'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
plt.xlim(left=x1)
plt.xlim(right=x2)
plt.ylim(bottom=y1)
plt.ylim(top=y2)
plt.axhline(linewidth=2, color='k')
plt.axvline(linewidth=2, color='k')

##plt.grid(True)
plt.grid(color='k', linestyle='-.', linewidth=0.5)
plt.show()

Bonne chance


0

De la même manière que le nuage de points, vous pouvez également utiliser un graphique normal avec un style de ligne circulaire. En utilisant le markersizeparamètre, vous pouvez ajuster le rayon d'un cercle:

import matplotlib.pyplot as plt

plt.plot(200, 2, 'o', markersize=7)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.