2012-02-09 42 views
83

Sorprendentemente, no encontré una descripción directa sobre cómo dibujar un círculo con matplotlib.pyplot (por favor, no pylab) tomando como centro de entrada (x, y) y radio r. Probé algunas variantes de esto:trazar un círculo con pyplot

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

... pero todavía no funcionó.

+0

Estoy seguro de que es posible hacer esto, pero matplotlib está destinado principalmente a trazar (es decir, aquí hay algunos datos, ponerlos en un gráfico), no dibujar, por lo que puede no ser del todo sencillo. –

+0

El radio de los puntos de dispersión se usa cada vez más para visualizar datos. Google charts los llama "trazados de burbujas". Gapminder.org es un buen ejemplo. Este * está * trazando, no dibujando. Busqué en el matplotlib github repo para "burbuja" y "radio de dispersión" en vano, así que no creo que esto esté en la lista de pendientes en cuanto a agregar una característica. –

+1

plt.scatter() toma un argumento de tamaño. Puede pasar listas para las coordenadas xey de los círculos, los radios de los círculos y los colores de los círculos. http://matplotlib.org/1.3.1/api/pyplot_api.html#matplotlib.pyplot.scatter. Mi error anterior, al pensar que dicha funcionalidad no estaba ya en matplotlib. –

Respuesta

118

es necesario agregar a un eje. Un Circle es una subclase de Artist, y un axes tiene un método add_artist.

He aquí un ejemplo de hacer esto:

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

Esto se traduce en la siguiente figura:

El primer círculo está en el origen, pero por defecto clip_on es True, por lo el círculo está recortado cuando se extiende más allá del axes. El tercer círculo (verde) muestra lo que sucede cuando no se recorta el Artist. Se extiende más allá de los ejes (pero no más allá de la figura, es decir, el tamaño de la figura es no ajustado automáticamente para trazar todos sus artistas).

Las unidades para x, y y radio corresponden a unidades de datos por defecto. En este caso, no grabé nada en mis ejes (fig.gca() devuelve los ejes actuales), y como los límites nunca se han establecido, tienen un valor predeterminado de xy entre 0 y 1.

Aquí hay una continuación del ejemplo, mostrando cómo las unidades cuestión:

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

que se traduce en:

se puede ver cómo me puse el llenado del segundo círculo para False, que es útil para rodear resultados clave (como mi punto de datos amarillo).

+4

Me gusta esta respuesta porque estás "dibujando" un círculo, en lugar de trazar . Aunque trazar habría sido mi primer instinto también. – samb8s

+0

¿Por qué artistas como Ellipse no respetan pylab.ion() o matplotlib.interactive (Verdadero)? Por ejemplo, una llamada a xlabel() (después de llamar a ion() o interactivo (True)) actualiza la figura inmediatamente, pero cualquier cosa que implique estos objetos Ellipse requiere un pylab.show() explícito o matplotlib.show(). –

+7

FYI: Parece que la clase Circle se ha movido de matplotlib.pyplot a matplotlib.patches desde que se escribió esta respuesta. – pavon

15
#!/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() 

O, si lo prefiere, mira a los path s, http://matplotlib.sourceforge.net/users/path_tutorial.html

+0

Ecuación trignométrica de un círculo y degreso 0 tp 360, que se traduce en 0 a 6.28319 radianes http://www.mathopenref.com/coordparamcircle.html –

13

Si desea que el "círculo" mantenga una relación de aspecto visual de 1, independientemente de las coordenadas de datos, podría utilizar el método 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() 

Image is a scatter plot. Five circles along the line y=10x have decreasing radii from bottom left to top right. Although the graph is square-shaped, the y-axis has 10 times the range of the x-axis. Even so, the aspect ratio of the circles is 1 on the screen.

+0

Muchas gracias. Estaba teniendo problemas con las proporciones de aspectos y los círculos. Scatter funcionaba como un encanto. – OptimusCrime

30

Si desea trazar un conjunto de círculos, es posible que desee ver this post o this gist (un poco más nuevo). La publicación ofrece una función llamada circles.

La función circles funciona como scatter, pero los tamaños de los círculos trazados se encuentran en la unidad de datos.

He aquí un ejemplo:

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) 

enter image description here

+0

¿Qué hace 'transform = ax.transAxes'? – Lee

+2

@Lee Eso es para el círculo en la esquina inferior derecha, transforma los datos en coordenadas de los ejes, es decir (1,1) significa esquina superior derecha en los ejes, (1,0) significa esquina inferior derecha, etc. –

+3

Esto debería ser parte de matplotlib. – JustAC0der

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

Una versión condensada rápida de la respuesta aceptada, que se adaptaba a mi necesidad de conectar rápidamente un círculo en un gráfico existente. Consulte la respuesta aceptada y otras respuestas para comprender los detalles.

Por cierto:

  • GCF() significa Obtener la figura actual
  • GCA() significa ponerse al día Eje
+2

¡Perfecto! exactamente lo que necesitaba ver en este momento. ¡Tu 'Por cierto' fue bastante útil también! 'dir (fig)' me muestra más de 30 métodos 'get', pero 'gca' no tiene ningún alias' get_current_axis'. Este tipo de respuestas fyi son maravillosas. – uhoh

+1

@jmn Solución agradable, rápida y fácil para principiantes. – Karlo

+2

puedes hacer 'plt.gca()' en lugar de 'plt.gcf(). Gca()' –

1

La extensión de la respuesta aceptada para un caso de uso común. En particular:

  1. Vea los círculos con una relación de aspecto natural.

  2. Extienda automáticamente los límites de los ejes para incluir los círculos recién trazados.

autónomo ejemplo:

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

Nota la diferencia entre ax.add_patch(..) y ax.add_artist(..): de los dos, sólo el primero hace que la maquinaria autoscaling tomar el círculo en cuenta (referencia: discussion), entonces después de ejecutar el código anterior obtenemos:

add_patch(..) vs add_artist(..)

Véase también: set_aspect(..) documentation.

Cuestiones relacionadas