trazar un círculo con pyplot

158

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

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

... pero aún así no funcionó.

Max Li
fuente
Estoy seguro de que es posible hacer esto, pero matplotlib está dirigido principalmente a trazar (es decir, aquí hay algunos datos, ponerlos en un gráfico), no dibujar, por lo que podría no ser del todo sencillo.
Thomas K
El radio de los puntos del diagrama de dispersión se usa cada vez más para visualizar datos. Los gráficos de Google los llaman "gráficos de burbujas". Gapminder.org es un buen ejemplo. Esto es trazar, no dibujar. Busqué en el repositorio matplotlib github "burbuja" y "radio de dispersión" en vano, así que no creo que esto esté en la lista de tareas pendientes en cuanto a agregar una función.
Bennett Brown,
1
plt.scatter () toma un argumento de tamaño. Puede pasar listas para las coordenadas x e y de los círculos, los radios de los círculos y los colores de los círculos. matplotlib.org/1.3.1/api/… . Mi error anterior, al pensar que dicha funcionalidad aún no estaba en matplotlib.
Bennett Brown,
3
Solo por mencionar: plt.Circle(..)dirige a matplotlib.patches.Circle(). Entonces, una solución sin pyplot sería circle = matplotlib.patches.Circle(..); axes.add_artist(circle).
ImportanceOfBeingErnest

Respuestas:

203

Necesita agregarlo a los ejes. A Circlees una subclase de an Artist, y an axestiene un add_artistmétodo.

Aquí hay 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 da como resultado la siguiente figura:

El primer círculo está en el origen, pero por defecto lo clip_onestá True, por lo que el círculo se recorta cuando se extiende más allá del axes. El tercer círculo (verde) muestra lo que sucede cuando no 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 no se ajusta automáticamente para representar a todos sus artistas).

Las unidades para x, y y radio corresponden a unidades de datos por defecto. En este caso, no tracé nada en mis hachas (fig.gca() devuelve los ejes actuales), y dado que los límites nunca se han establecido, el valor predeterminado es un rango x e y de 0 a 1.

Aquí hay una continuación del ejemplo, que muestra cómo importan las unidades:

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

lo que resulta en:

Puede ver cómo configuro el relleno del segundo círculo False, lo cual es útil para rodear los resultados clave (como mi punto de datos amarillo).

Yann
fuente
44
Me gusta esta respuesta porque estás "dibujando" un círculo, en lugar de trazar. Aunque tramar habría sido mi primer instinto también
samb8s
77
FYI: Parece que la clase Circle se ha movido de matplotlib.pyplot a matplotlib.patches desde que se escribió esta respuesta.
Pavón
66
¡Pero pero pero los círculos son ovales!
rubenvb
1
@rubenvb vea mi otra respuesta: stackoverflow.com/questions/9230389/…
Yann
3
@pavon Para mí se matplotlib.pyplot.Circle == matplotlib.patches.Circleevalúa True, por lo que probablemente sean alias.
Evgeni Sergeev
66
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, para conectar rápidamente un círculo en una trama existente. Consulte la respuesta aceptada y otras respuestas para comprender los detalles.

Por cierto:

  • gcf() significa Obtener figura actual
  • gca() significa Obtener eje actual
jmn
fuente
44
¡Perfecto! exactamente lo que necesitaba ver en este momento. ¡Tu 'Por cierto' también fue muy útil! dir(fig)me muestra más de 30 métodos 'get', pero gcano tiene un get_current_axisalias. Este tipo de respuestas para tu información son maravillosas.
uhoh
66
en realidad puedes hacer en plt.gca()lugar deplt.gcf().gca()
Andre Holzner
38

Si desea trazar un conjunto de círculos, es posible que desee ver esta publicación o esta esencia (un poco más nueva). La publicación ofrecía una función llamada circles.

La función circlesfunciona como scatter, pero los tamaños de los círculos trazados están en la unidad de datos.

Aquí hay 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)

ingrese la descripción de la imagen aquí

Syrtis Major
fuente
¿Qué transform=ax.transAxeshacer?
Lee
3
@Lee Eso es para el círculo en la esquina inferior derecha, transforma los datos en coordenadas de ejes, es decir (1,1) significa esquina superior derecha en ejes, (1,0) significa esquina inferior derecha, etc.
Syrtis Major
44
Esto debería ser parte de matplotlib.
JustAC0der
¿Se puede usar esto con mplleaflet? Si es así, ¿podría dar un ejemplo, por favor?
François M.
@fmalaussena Como este fragmento de código es puro matplotlib, supongo que debería ser compatible, mplleafletaunque nunca lo intenté.
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()

O, si lo prefiere, mire paths, http://matplotlib.sourceforge.net/users/path_tutorial.html

ev-br
fuente
2
Ecuación trignométrica de un círculo y degresión 0 tp 360, que se traduce de 0 a 6.28319 radianes mathopenref.com/coordparamcircle.html
Alex Punnen
19

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

La imagen es un diagrama de dispersión.  Cinco círculos a lo largo de la línea y = 10x tienen radios decrecientes de abajo a la izquierda a arriba a la derecha.  Aunque el gráfico tiene forma cuadrada, el eje y tiene 10 veces el rango del eje x.  Aun así, la relación de aspecto de los círculos es 1 en la pantalla.

Bennett Brown
fuente
11

Extender la respuesta aceptada para un caso de uso común. En particular:

  1. Ver los círculos en una relación de aspecto natural.

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

Ejemplo autónomo:

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

Tenga en cuenta la diferencia entre ax.add_patch(..)y ax.add_artist(..): de los dos, solo el primero hace que la maquinaria de autoescalado tenga en cuenta el círculo (referencia: discusión ), por lo que después de ejecutar el código anterior obtenemos:

add_patch (..) vs add_artist (..)

Ver también: set_aspect(..)documentación .

Evgeni Sergeev
fuente
En python3, debe sacar fig, ax = plt.subplots(), de lo contrario obtendrá dos ventanas (una está en blanco).
albus_c
1

Veo tramas con el uso de (.circle) pero en función de lo que quieras hacer, también puedes probar esto:

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)

Diagrama de círculo concéntrico simple usando puntos de progreso lineales

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

Puntos en un círculo de un problema de clasificación.

inyang kpongette
fuente
0

Hola, he escrito un código para dibujar un círculo. Ayudará a dibujar todo tipo de círculos. La imagen muestra el círculo con radio 1 y centro en 0,0 El centro y el radio se pueden editar de cualquier elección.

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

Buena suerte

AJEET
fuente
0

De manera similar al diagrama de dispersión, también puede usar el diagrama normal con estilo de línea circular. Usando el markersizeparámetro puede ajustar el radio de un círculo:

import matplotlib.pyplot as plt

plt.plot(200, 2, 'o', markersize=7)
Marcin Szałajski
fuente