关于matplotlib:pyplot散点图标记大小

pyplot scatter plot marker size

在散点图的pyplot文档中:

1
2
3
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:
size in points^2. It is a scalar or an array of the same length as x and y.

points^2是哪种单位? 这是什么意思? s=100表示10 pixel x 10 pixel吗?

基本上,我试图制作具有不同标记大小的散点图,并且我想弄清楚s数字是什么意思。


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

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

1
2
3
4
5
6
# 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()

enter image description here

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

1
2
3
4
5
6
# 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()

enter image description here

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

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

希望这可以帮助!

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

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

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


因为这里的其他答案都声称s表示标记的区域,所以我添加了此答案以明确说明不一定是这种情况。

磅数^ 2

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

s : scalar or array_like, shape (n, ), optional
size in points^2. Default is rcParams['lines.markersize'] ** 2.

这可以从字面上看。为了获得一个x点大的标记,您需要对该数字求平方并赋予s自变量。

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

enter image description here

1
2
3
4
5
6
7
8
9
10
11
12
13
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
  • 对于其他标记,甚至可能与标记的面积没有任何明显的关系。

enter image description here

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

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

enter image description here

有什么要点?

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

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

1
1 point == fig.dpi/72. pixels

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

enter image description here
enter image description here
enter image description here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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()

如果您对数据单位中的散布感兴趣,请检查此答案。


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

1
2
3
4
5
6
7
8
9
10
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()

从这里

enter image description here


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

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

enter image description here

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


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

1
2
3
4
5
6
7
8
9
10
11
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)

enter image description here

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


如果圆的大小与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]