pyplot散点图标记大小


376

在散点图的pyplot文档中:

matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None,
                          vmin=None, vmax=None, alpha=None, linewidths=None,
                          faceted=True, verts=None, hold=None, **kwargs)

标记尺寸

s:以磅为单位的大小^ 2。它是标量或与x和y长度相同的数组。

什么单位points^2?这是什么意思?是否s=100意味10 pixel x 10 pixel

基本上,我正在尝试制作具有不同标记大小的散点图,并且我想弄清楚s数字的含义。


非常确定这些点与字体所使用的单位相同。
tacaswell 2013年

@tcaswell,您的意思s=20是说标记的大小等于fontsize=20字母的大小吗?
LWZ

不,面积将是20点^ 2,一个fontsize=20字母高20点(或者字体中的参考字符高20点)。
tacaswell

23
matplotlib.pyplot.plot()具有ms参数(markersize)的等效matplotlib.pyplot.scatter()参数ssize)。提醒您
。– niekas 2014年

@neikas在我看来不是,因为一个是像素(markersize),另一个是这个奇怪的平方点单位(size)。这一直令我感到困惑,但是我认为这与散点图标记大小用于以视觉上成比例的方式表示数量有关。
heltonbiker

Answers:


406

这种定义大小的方法可能有些混乱,但是您基本上是在指定标记的区域。这意味着,要使标记的宽度(或高度)加倍,您需要增加s4倍。[因为A = W H =>(2W)(2H)= 4A]

但是,以这种方式定义标记的大小是有原因的。由于将面积缩放为宽度的平方,因此实际上加倍宽度似乎会使大小增加2倍以上(实际上,将其增加4倍)。要查看此内容,请考虑以下两个示例以及它们产生的输出。

# doubling the width of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*4**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

在此处输入图片说明

请注意大小如何快速增加。如果相反,我们有

# doubling the area of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*2**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

在此处输入图片说明

现在,标记的外观大小以直观的方式大致线性增加。

至于“点”的确切含义,出于绘图目的,它是任意的,您可以按常数缩放所有尺寸,直到看起来合理为止。

希望这可以帮助!

编辑:(以回应@Emma的评论)

我的措辞可能令人困惑。问题被问到是否将圆的宽度加倍,因此在每个圆的第一张图片中(当我们从左向右移动时)它的宽度是前一个圆的两倍,因此对于面积而言,这是底数为4的指数。每个圆的面积是最后一个圆的两倍,最后一个圆的底数为2。

但是,这是第二个示例(我们正在缩放区域),该区域看起来加倍,使圆眼大两倍。因此,如果我们希望圆出现n更大的因数,我们将以n不为半径的因数来增加面积,因此表观大小会随面积线性缩放。

编辑以显示@TomaszGandor的评论:

这是标记大小的不同功能的外观:

指数,平方或线性大小

x = [0,2,4,6,8,10,12,14,16,18]
s_exp = [20*2**n for n in range(len(x))]
s_square = [20*n**2 for n in range(len(x))]
s_linear = [20*n for n in range(len(x))]
plt.scatter(x,[1]*len(x),s=s_exp, label='$s=2^n$', lw=1)
plt.scatter(x,[0]*len(x),s=s_square, label='$s=n^2$')
plt.scatter(x,[-1]*len(x),s=s_linear, label='$s=n$')
plt.ylim(-1.5,1.5)
plt.legend(loc='center left', bbox_to_anchor=(1.1, 0.5), labelspacing=3)
plt.show()

2
我可能会误解您的观点,但是在您的第二个示例中,您正在呈指数增长(s = [20,40,80,160,320,640]),并说这给了我们很好的线性外观尺寸增加。如果线性增加大小(例如s = [20,40,60,80,100,120])为我们提供线性外观的结果会更有意义吗?
艾玛(Emma)

@Emma您的直觉是正确的,对我而言,它的用词很差(或者x轴缩放比例选择不佳)。我在编辑中解释了更多内容,因为评论太长了。
2013年

1
是否可以s根据图形窗口的大小更改值?我的意思是,如果我们最大化图形窗口,我希望有更大的尺寸标记。
Sigur

2
很好的例子(只是必要的东西!)。这不应该是4 ** nand 2 ** n,而是n ** 4and n ** 2。对于2 ** n第二个图,圆直径不线性缩放。它仍然运行得太快(仅在顶部不远)。
Tomasz Gandor

1
简而言之-第二个图显示了指数的平方根-这是另一个指数,只是陡峭程度有所降低。
Tomasz Gandor

217

由于此处的其他答案要求s表示标记的区域,因此我添加此答案以明确说明不一定是这种情况。

磅数^ 2

的参数splt.scatter表示markersize**2。如文档所述

s:标量或类似array_,形状(n,),可选
大小,以磅为单位^ 2。默认值为rcParams ['lines.markersize'] ** 2。

这可以从字面上看。为了获得一个x点大的标记,您需要对该数字求平方并将其提供给s参数。

因此,线图的标记大小与散点大小参数之间的关系为平方。为了生成与大小为10点的绘图标记相同大小的散点标记,您将因此称为scatter( .., s=100)

在此处输入图片说明

import matplotlib.pyplot as plt

fig,ax = plt.subplots()

ax.plot([0],[0], marker="o",  markersize=10)
ax.plot([0.07,0.93],[0,0],    linewidth=10)
ax.scatter([1],[0],           s=100)

ax.plot([0],[1], marker="o",  markersize=22)
ax.plot([0.14,0.86],[1,1],    linewidth=22)
ax.scatter([1],[1],           s=22**2)

plt.show()

与“区域”的连接

那么,为什么涉及s参数的其他答案甚至文档都谈到“区域” 呢?

当然,点** 2的单位是面积单位。

  • 对于方形标记的特殊情况,标记marker="s"的面积确实直接是s参数的值。
  • 对于圆,圆的面积为area = pi/4*s
  • 对于其他标记,甚至可能与标记的面积没有任何明显的关系。

在此处输入图片说明

但是,在所有情况下,标记的面积都与s参数成正比。这是将其称为“区域”的动机,即使在大多数情况下并非如此。

从某种意义上说,指定散射标记的大小与标记的面积成正比,这是有意义的,因为在比较不同的贴片时,可以感觉到的是标记的面积,而不是侧面的长度或直径。即加倍基础数量应使标记的面积增加一倍。

在此处输入图片说明

有什么要点?

到目前为止,以点为单位给出了对分散标记的含义的答案。点通常用于排版中,其中以点指定字体。此外,线宽通常以磅为单位指定。matplotlib中标准的点大小是每英寸72点(ppi)-因此1点是1/72英寸。

能够以像素而不是点为单位指定大小可能会很有用。如果数字dpi也为72,则一点就是一个像素。如果数字dpi不同(matplotlib默认为fig.dpi=100),

1 point == fig.dpi/72. pixels

因此,对于不同的数字dpi,散布标记的大小(以磅为单位)看起来会有所不同,但可以产生10 x 10像素^ 2的标记,该标记始终覆盖相同数量的像素:

在此处输入图片说明 在此处输入图片说明 在此处输入图片说明

import matplotlib.pyplot as plt

for dpi in [72,100,144]:

    fig,ax = plt.subplots(figsize=(1.5,2), dpi=dpi)
    ax.set_title("fig.dpi={}".format(dpi))

    ax.set_ylim(-3,3)
    ax.set_xlim(-2,2)

    ax.scatter([0],[1], s=10**2, 
               marker="s", linewidth=0, label="100 points^2")
    ax.scatter([1],[1], s=(10*72./fig.dpi)**2, 
               marker="s", linewidth=0, label="100 pixels^2")

    ax.legend(loc=8,framealpha=1, fontsize=8)

    fig.savefig("fig{}.png".format(dpi), bbox_inches="tight")

plt.show() 

如果您对散布数据单位感兴趣,请查看此答案


想知道如何计算要赋予散布的s参数以获得一个圆,该圆在图的实际坐标中覆盖0.1的直径(以便填补从(0 ,0)到(1,1)?
Anatoly Alekseev

@AnatolyAlekseev 这个问题应该回答。
ImportanceOfBeingErnest

21

您可以在plot方法中使用markersize指定圆的大小

import numpy as np
import matplotlib.pyplot as plt

x1 = np.random.randn(20)
x2 = np.random.randn(20)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(x1, 'bo', markersize=20)  # blue circle with size 10 
plt.plot(x2, 'ro', ms=10,)  # ms is just an alias for markersize
plt.show()

这里

在此处输入图片说明


现在的问题是关于散点图,并在matplotlib两个绘图函数有不同的参数(markersize情节,和小号散射)。因此,此答案不适用。
Dom

3
@Dom我投票赞成,因为即使当我搜索“ pyplot plot marker size”时,该问题也会作为google中的第一个结果弹出,因此此答案很有帮助。
Przemek D

我知道剧情方法和散射方法是在PLT不同,但它们都可以实现“散点图”并调整markersize,所以这个答案是另一个工作周围,如果你使用图解法@Dom
肇庆

18

它是标记的区域。我的意思是,如果您拥有s1 = 1000,则s2 = 4000每个圆的半径之间的关系为:r_s2 = 2 * r_s1。请参见下图:

plt.scatter(2, 1, s=4000, c='r')
plt.scatter(2, 1, s=1000 ,c='b')
plt.scatter(2, 1, s=10, c='g')

在此处输入图片说明

看到帖子时,我也有同样的疑问,所以我做了这个例子,然后在屏幕上用尺子测量半径。


这是最干净,最无脂肪的答案。谢谢
Ayan Mitra

6

我也尝试为此目的最初使用“分散”。在浪费大量时间后-我决定采用以下解决方案。

import matplotlib.pyplot as plt
input_list = [{'x':100,'y':200,'radius':50, 'color':(0.1,0.2,0.3)}]    
output_list = []   
for point in input_list:
    output_list.append(plt.Circle((point['x'], point['y']), point['radius'], color=point['color'], fill=False))
ax = plt.gca(aspect='equal')
ax.cla()
ax.set_xlim((0, 1000))
ax.set_ylim((0, 1000))
for circle in output_list:    
   ax.add_artist(circle)

在此处输入图片说明

这是基于对这个问题的答案


非常有帮助。但是为什么要使用两个循环?
catchantot '18

1
@grabantot没有理由,只是没想太多。
艾克

2

如果圆的大小对应于中参数s=parameter的平方,则为您附加到size数组的每个元素分配平方根,如下所示:s=[1, 1.414, 1.73, 2.0, 2.24]这样,当使用这些值并返回它们时,它们的相对大小将增加平方级数的平方根,返回线性级数。

如果我要平方每个平方,因为它将输出到绘图中:output=[1, 2, 3, 4, 5]。尝试列表解释:s=[numpy.sqrt(i) for i in s]


1
应该不i in output应该吗?
Sigur
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.