【问题标题】:pyplot scatter plot marker sizepyplot 散点图标记大小
【发布时间】:2013-01-27 11:17:03
【问题描述】:

在散点图的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)

标记大小

: 大小以点^2。它是与 x 和 y 长度相同的标量或数组。

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

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

【问题讨论】:

  • 很确定点与字体使用的单位相同。
  • @tcaswell,你的意思是s=20 表示标记大小等于fontsize=20 字母的大小?
  • matplotlib.pyplot.plot() 具有 ms 参数 (markersize) 等效于 matplotlib.pyplot.scatter() 参数 s (size)。只是一个提醒..
  • @neikas 在我看来它们不是,因为一个是像素(标记大小),另一个是这个奇怪的平方点单位(大小)。这一直让我感到困惑,但我认为这与散点图标记大小用于以视觉比例方式表示数量有关。
  • @heltonbiker 是正确的。如果要将plot函数中的markersizescatter函数中的s相匹配,则需要将其平方,即s = markersize**2

标签: matplotlib marker scatter


【解决方案1】:

这可能是定义大小的一种有点混乱的方式,但您基本上是在指定标记的区域。这意味着,要将标记的宽度(或高度)加倍,您需要将 s 增加 4 倍。[因为 A = WH => (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()

【讨论】:

  • 我可能误解了你的观点,但在你的第二个例子中,你正在以指数方式增加 s (s=[20, 40, 80, 160, 320, 640]) 并说这给了我们一个漂亮的线性外观尺寸增加。如果线性增加尺寸(例如 s=[20, 40, 60, 80, 100, 120])给我们带来线性外观的结果不是更有意义吗?
  • @Emma 你的直觉是对的,我的措辞很糟糕(或者 x 轴缩放的选择很糟糕)。我在编辑中解释了更多内容,因为评论太长了。
  • 是否可以根据图形窗口的大小更改s的值?我的意思是,如果我们最大化图形窗口,我希望有更大的尺寸标记。
  • 很好的例子(只是必要的东西!)。这不应该是4 ** n2 ** n,而是n ** 4n ** 2。对于2 ** n,第二个图在圆直径方面不是线性缩放的。它仍然过快(只是没有超过顶部)。
  • 简而言之 - 第二个图显示指数的平方根 - 这是另一个指数,只是稍微不那么陡峭。
【解决方案2】:

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

以点为单位的大小^2

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

s : 标量或类似数组,形状 (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 参数成比例。这就是将其称为“区域”的动机,尽管在大多数情况下并非如此。

到目前为止,根据与标记面积成比例的某个量来指定散射标记的大小是有意义的,因为在比较不同的补丁时感知到的是标记的面积,而不是其边长或直径。 IE。将基础数量加倍应该使标记的面积加倍。

什么是积分?

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

能够以像素而不是点为单位指定大小可能很有用。如果图形 dpi 也是 72,则 1 点是 1 个像素。如果图形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() 

如果您对数据单元的分散感兴趣,请查看this answer

【讨论】:

  • 想知道如何计算 s 参数给 scatter 以获得一个覆盖直径的圆,比如说,在绘图的实际坐标中为 0.1(以便填补假设 0.4和 0.5 在从 (0,0) 到 (1,1) 的图上?
  • @AnatolyAlekseev 这应该由this 问题回答。
  • @ImportanceOfBeingErnest 您能否解释一下如何根据传递的s 参数获取散点半径?我以为是np.sqrt(s)/2*.com/q/64399664/9900084
【解决方案3】:

您可以在绘图方法中使用ma​​rkersize来指定圆的大小

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

来自here

【讨论】:

  • 问题是关于散点图的,在 matplotlib 中,两个绘图函数具有不同的参数(markersize 用于 plots 代表分散)。所以这个答案不适用。
  • @Dom 我赞成,因为即使我搜索“pyplot plot marker size”,这个问题也会作为谷歌的第一个结果弹出,所以这个答案有帮助。
  • 我知道绘图方法和散点法在 plt 中是不同的,但它们都可以实现“散点图”并调整标记大小,所以如果您使用绘图方法@Dom,这个答案只是另一种解决方法
【解决方案4】:

它是标记的区域。我的意思是如果你有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')

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

【讨论】:

  • 这是最干净、最无脂肪的答案。谢谢
  • +1,实际上smarkersize快捷方式,就像ccolor 的快捷方式一样。 Reference。如果 matplotlib 文档可以像这个答案一样简单,而不是在每一行添加噪音......
【解决方案5】:

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

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)

这是基于对this question的回答

【讨论】:

  • 非常有帮助。但是为什么要使用两个循环呢?
  • @grabantot 没有理由,只是没有想太多。
【解决方案6】:

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

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

【讨论】:

  • 应该是i in output 不应该?
  • 同意@Sigur