使用pyplot绘制圆形

255

令人惊讶的是,我没有找到一个简单明了的描述如何使用matplotlib.pyplot(请勿使用pylab)以中心点(x,y)和半径r作为输入绘制圆形的方法。我尝试了一些变体:

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

...但仍然没有使其工作。


我相信这是可能的,但Matplotlib主要针对绘图(即给定一些数据,将它们放在图表上),而不是绘画,因此可能并不是完全直观的。 - Thomas K
散点图点的半径越来越被用于可视化数据。Google charts称之为“气泡图”。Gapminder.org是一个很好的例子。这是绘图,不是手绘。我在matplotlib github库中搜索了“bubble”和“scatter radius”,但没有找到相关内容,因此我认为这不在添加功能的待办列表中。 - Bennett Brown
1
plt.scatter()еҮҪж•°зЎ®е®һеҸҜд»ҘжҺҘеҸ—дёҖдёӘsizeеҸӮж•°гҖӮдҪ еҸҜд»Ҙдј йҖ’еҢ…еҗ«еңҶзҡ„xе’Ңyеқҗж ҮгҖҒеҚҠеҫ„д»ҘеҸҠйўңиүІзҡ„еҲ—иЎЁгҖӮhttp://matplotlib.org/1.3.1/api/pyplot_api.html#matplotlib.pyplot.scatterгҖӮжҲ‘д№ӢеүҚзҡ„й”ҷиҜҜжҳҜи®Өдёәиҝҷж ·зҡ„еҠҹиғҪеңЁmatplotlibдёӯиҝҳдёҚеӯҳеңЁгҖӮ - Bennett Brown
3
只是提一下:plt.Circle(..)指向matplotlib.patches.Circle()。因此,一个没有pyplot的解决方案是circle = matplotlib.patches.Circle(..); axes.add_artist(circle) - ImportanceOfBeingErnest
9个回答

328

您需要将其添加到一个坐标轴(axes)上。一个CirclePatch的一个子类,而一个axes具有一个add_patch方法。(您还可以使用add_artist方法,但不建议这样做。)

下面是一个这样做的例子:

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_patch(circle1)
ax.add_patch(circle2)
ax.add_patch(circle3)

fig.savefig('plotcircles.png')

以下是该代码的结果:

第一个圆在原点,但默认情况下clip_onTrue,当圆超出axes范围时会被裁剪。第三个(绿色)圆显示了在不裁剪Artist的情况下会发生什么。它超出了轴的范围(但没有超出图片大小,即图片大小并没有自动调整以绘制您所有的艺术家)。

x、y和半径的单位默认情况下对应于数据单位。在这种情况下,我没有在我的轴上绘制任何东西(fig.gca()返回当前轴),并且由于限制从未被设置,它们默认为从0到1的x和y范围。

以下是示例的继续,展示了单位的影响:

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_patch(circle1)
ax.add_patch(circle2)
ax.add_patch(circle3)
fig.savefig('plotcircles2.png')

这导致:

你可以看到我将第二个圆的填充设置为False,这对于围绕关键结果(例如我的黄色数据点)非常有用。


4
我喜欢这个回答,因为你是“画”一个圆圈,而不是绘制它。虽然我的第一反应也是绘制。 - samb8s
9
FYI:从这个答案发布之后,似乎Circle类已经从matplotlib.pyplot移动到了matplotlib.patches。 - pavon
13
但是,但是,这些圆形是椭圆形的! - rubenvb
2
@rubenvb 请查看我的另一个回答:https://dev59.com/Tmox5IYBdhLWcg3waziQ#9232513 - Yann
4
对我来说,matplotlib.pyplot.Circle == matplotlib.patches.Circle 的结果为 True,因此它们很可能是别名。 - Evgeni Sergeev
显示剩余7条评论

110
import matplotlib.pyplot as plt

circle1 = plt.Circle((0, 0), 0.2, color='r')
plt.gca().add_patch(circle1)

快速简明版本的被接受答案,以快速将圆形插入现有图中。请参考被接受的答案和其他答案了解详情。

顺便说一下:

  • gca() 意思是获取当前轴

5
太好了!这正是我现在需要看到的。你的“顺便提一下”也很有帮助!dir(fig)向我展示了超过30个“get”方法,但是gca没有“get_current_axis”的别名。这种FYI(供参考)的回答非常棒。 - uhoh
10
你可以使用plt.gca()代替plt.gcf().gca()。 - Andre Holzner

43
如果您想绘制一组圆形,您可以参考此帖子这个代码片段(更新较新)。该帖子提供了一个名为circles的函数。
函数circles类似于scatter,但所绘制圆的尺寸是以数据单位表示的。
以下是一个示例:
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


transform=ax.transAxes 是什么意思? - wsdzbm
3
@Lee 针对右下角的圆圈,将数据转换为坐标轴坐标,即(1,1)表示坐标轴中的右上角,(1,0)表示右下角,依此类推。 - Syrtis Major
5
这应该是matplotlib的一部分。 - JustAC0der
这个能和 mplleaflet 一起使用吗?如果可以的话,能否提供一个例子? - François M.
@fmalaussena 这段代码片段是纯matplotlib的,我猜它应该与mplleaflet兼容,尽管我从未尝试过。 - Syrtis Major

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

或者,如果您喜欢的话,可以查看 path(路径),http://matplotlib.sourceforge.net/users/path_tutorial.html


2
三角函数方程式的圆和度数从0到360,相当于0到6.28319弧度 http://www.mathopenref.com/coordparamcircle.html - Alex Punnen
请问你为什么在函数名前面加上 *,比如 *xy(r, phis)。谢谢。 - sleeve chen
@sleevechen * 将函数返回的 2 元组解包为单独的参数。请参阅 https://runestone.academy/runestone/books/published/fopp/Tuples/UnpackingArgumentsToFunctions.html - Stanley Bak

19

如果您希望“圆形”保持视觉纵横比为1,无论数据坐标如何,您可以使用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()

图像是一个散点图。沿着直线y=10x有五个圆,从左下到右上半径逐渐减小。虽然图形呈正方形,但y轴的范围是x轴的十倍。即使如此,屏幕上圆的纵横比为1。


15

扩展常见用例的接受答案。特别是:

  1. 以自然宽高比查看圆。

  2. 自动扩展轴限制以包括新绘制的圆。

自包含示例:

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

注意 ax.add_patch(..)ax.add_artist(..) 之间的区别:两者中只有前者考虑了自动缩放机制(参考:讨论),因此在运行上述代码后,我们得到:

add_patch(..) vs add_artist(..)

另请参阅:set_aspect(..) 文档


在Python3中,你需要去掉 fig, ax = plt.subplots(),否则你会得到两个窗口(其中一个是空白的)。 - albus_c

13

我看到使用 (.circle) 绘制的图表,但根据你想要做什么,你也可以尝试这个:

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)

使用线性进度点的简单同心圆图

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

分类问题中的圆圈点图示。


1
什么是 make_blobs - iacopo
2
scikit-learn有一个make_blobs函数:https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html - Arun Das

0
与散点图类似,您也可以使用带圆形线条样式的普通图。使用markersize参数可以调整圆的半径:
import matplotlib.pyplot as plt

plt.plot(200, 2, 'o', markersize=7)

0

你好,我已经编写了一个绘制圆形的代码。 它可以帮助绘制各种类型的圆形。 图像显示半径为1,中心在0,0的圆 中心和半径可以根据需要进行编辑。

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

祝你好运


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接