在同一坐标系中绘制散点图和标记大小

11 投票
2 回答
17239 浏览
提问于 2025-04-16 11:53

我正在尝试在pylab中以编程方式显示各种类型的图表。pylab的散点图函数可以在不同的坐标位置上显示标记,但标记的大小是以像素为单位的。这对于日常的图表绘制来说是合理的。但是,我想要在同样的坐标系中给出坐标和标记的大小!例如,下面的代码在(0.0,0.0)和(0.5,0.5)的位置上显示两个大小为20的圆圈。因为它们的半径比中心之间的距离大得多,所以它们应该几乎完全重叠。然而,它们并没有重叠,因为大小是以像素为单位,而位置是以坐标轴的坐标为单位。

import pylab
pylab.scatter([0,0.5], [0,0.5], s=20, c='b', marker='o')

有没有办法让散点图(或者绘制任何形状、线条等)在同样的坐标系中给出大小和位置?我对矢量图形输出(比如pdf、svg等)很感兴趣。

2 个回答

3

补丁集合是一个更好的选择,如果你真的想让它看起来像plt.scatter。假设你想在数据单位中绘制一组具有给定半径的圆,你可以看看这篇帖子,里面提供了一个很好用的函数,叫做circles

如果你想使用其他标记,比如方形或多边形,你可以根据dr jimbob的回答,重新编写这个函数,使用相应的补丁。

这里有一个例子

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

#plot a set of circle
a = arange(11)
circles(a, a, s=a*0.2, c=a, alpha=0.5, ec='none')
colorbar() 

#plot a circle (the lower-right one)
circles(1, 0, s=0.4, c='r', ls='--', lw=5, fc='none', transform=ax.transAxes)

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

在这里输入图片描述

12

pylab.scatter这个函数用来画散点图时,点的大小是以平方点数为单位的。这种大小是和坐标轴无关的,因为散点图的特点就是这样(如果你放大某个区域,点的大小不应该变大,这样就没意义了)。

如果你想画固定大小的圆圈,应该使用pylab中的圆形命令。

import pylab
axes = pylab.axes()
circle1 = pylab.Circle((0,0), radius=20, alpha=.5)
circle2 = pylab.Circle((0.5,0.5), radius=20, alpha=.5)
axes.add_patch(circle1)
axes.add_patch(circle2)
pylab.axis('scaled')
pylab.show()

如果你需要一些类似散点图的功能,可以尝试下面的方法:

import pylab
import matplotlib

def my_circle_scatter(axes, x_array, y_array, radius=0.5, **kwargs):
    for x, y in zip(x_array, y_array):
        circle = pylab.Circle((x,y), radius=radius, **kwargs)
        axes.add_patch(circle)
    return True

def my_square_scatter(axes, x_array, y_array, size=0.5, **kwargs):
    size = float(size)
    for x, y in zip(x_array, y_array):
        square = pylab.Rectangle((x-size/2,y-size/2), size, size, **kwargs)
        axes.add_patch(square)
    return True

def my_polygon_scatter(axes, x_array, y_array, resolution=5, radius=0.5, **kwargs):
    ''' resolution is number of sides of polygon '''
    for x, y in zip(x_array, y_array):
        polygon = matplotlib.patches.CirclePolygon((x,y), radius=radius, resolution=resolution, **kwargs)
        axes.add_patch(polygon)
    return True

axes=pylab.axes()
my_circle_scatter(axes, [0,0.5], [0,0.5], radius=2, alpha=.5, color='b')
my_square_scatter(axes, [-3,-4,2,3], [1,-3,0,3], size=.5, alpha=.5, color='r')
my_polygon_scatter(axes, [-1,-2,3], [-3,0,3], radius=.5, resolution=3, alpha=.5, color='g')
my_polygon_scatter(axes, [4,1.5,3], [2,-1,-3], radius=.5, resolution=5, alpha=.5, color='k')
pylab.axis('scaled')
pylab.axis([-5,5,-5,5])
pylab.show()

可以查看 http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.patches 来了解其他可以绘制的对象。

第一个代码片段的示例输出: matplotlib circles

第二个代码片段的示例输出: matplotlib scatter plot

给Griff的补充:如果你想为每个点设置不同的半径,可以用简单的方法来实现:

def my_circle_scatter_radii(axes, x_array, y_array, radii_array, **kwargs):
    for (x, y, r) in zip(x_array, y_array, radii_array):
        circle = pylab.Circle((x,y), radius=r, **kwargs)
        axes.add_patch(circle)
    return True

同时处理这两种情况的逻辑也很简单(比如,检查半径数组是否是整数或浮点数,如果是,就把它变成一个数组)。

撰写回答