【问题标题】:How to add a label to a scatter, with multiple variables?如何将标签添加到具有多个变量的散点图?
【发布时间】:2020-03-30 21:06:51
【问题描述】:

我创建了一个散点图,其中的点随表内某些大小的行星而变化。 为此,我使用了这个函数:

#data:
x=composition
y=composition
z=planetary_radii

#some stuff to let the scatter organized:
left, width = 0.1, 0.7
bottom, height = 0.1, 0.7
rect_scatter = [left, bottom, width, height]
ax_scatter = plt.axes(rect_scatter)

#the function that separates the dots in different colors:
colors = []
for i in z:
  if i > 8:
    colors.append('r')
  elif i<8 and i>4:
    colors.append('b')
  elif i<4 and i>2:
    colors.append('g')
  elif i<2:
    colors.append('orange')
  else:
    colors.append('y')

# the scatter plot:
ax_scatter.scatter(x, y,c=colors, s=10)

然后,我希望这些点位于标签中,但名称不同于“g”、“orange”等。它们会像“Radii>8”、“4”

我怎样才能做到这一点?我是否必须创建另一个函数才能使用 db.scatter 中的标签参数?

这张图片显示了没有标签的散点图:

【问题讨论】:

  • 将您的数据拆分为列表。然后单独绘制列表plt.plot( a, ..., label = 'a')(您可以选择颜色),或者如果您在循环中有很多plt.plot( aa[i], ..., label = label[i]),其中 label[i] 是标签列表。 (颜色将是自动的,或者您可以使用要在循环中分配的颜色列表)。然后添加一行plt.legend()
  • 最新的matplotlib版本(3.1)可以做到这一点:matplotlib.org/3.1.0/gallery/lines_bars_and_markers/…
  • @Solvalou 我试过使用这个函数:legend1 = ax_scatter.legend(*scatter.legend_elements(), loc="lower right", title="Classes") ax_scatter.add_artist(legend1) 但我收到以下错误消息:'PathCollection' 对象没有属性'legend_elements'。如何应对?
  • 这可能是因为您使用的是旧版本的matplotlib,因为只有最新版本才支持此功能!

标签: python matplotlib scatter-plot


【解决方案1】:

我有一个使用最新版本的matplotlib 3.1.2 的解决方案。要安装它,请执行

pip install -U matplotlib

但请注意它仅适用于 Python3,因为 Python2 仅支持 matplotlib 直到版本 2。


在此处查看完整代码:

#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap

x=composition
y=composition
z=planetary_radii

# some stuff to let the scatter organized:
left, width = 0.1, 0.7
bottom, height = 0.1, 0.7
rect_scatter = [left, bottom, width, height]
ax_scatter = plt.axes(rect_scatter)

# the function that separates the dots in different classes:
classes = np.zeros( len(x) )    # z > 8
classes[(z <= 8) & (z > 4)] = 1
classes[(z <= 4) & (z > 2)] = 2
classes[z <= 2] = 3

# create color map:
colors = ['r', 'b', 'g', 'orange', 'y']
cm = LinearSegmentedColormap.from_list('custom', colors, N=len(colors))

# the scatter plot:
scatter = ax_scatter.scatter(x, y, c=classes, s=10, cmap=cm)
lines, labels = scatter.legend_elements()

# legend with custom labels
labels = [r'Radii $> 8$', r'$4 <$ Radii $\leq 8$', 
          r'$2 <$ Radii $\leq 4$', r'Radii $\leq 2$']
legend = ax_scatter.legend(lines, labels,
                    loc="lower right", title="Classes")
ax_scatter.add_artist(legend)
plt.show()

定义了四个类,它们取决于z 的值。请注意,由于您排除了一些值(如 4 和 8),所以我通过使用较小的等号稍微更改了范围。之后,定义了一个自定义颜色映射,其中设置了相应类的颜色。结果被提供给散点图,通过调用legend_elements() 可以从中得到lineslabels。您现在可以随意更改这些标签,最后将它们提供给ax_scatter.legend()。这里还可以指定图例的标题。

【讨论】:

  • 嗯,这很好,谢谢!还有一个问题:在这个新的“类”方法中,你用来分隔 z 的值,我怎样才能添加与数字不同的值? (在我的表中,我有一些 NaN 值也需要计算在散点图中)
  • 不客气。您可以使用 np.isnan(z) 过滤 NaN。但是你想用这些做什么?由于它们不是数字,因此您当然不能绘制它们。你想数一数吗?然后你可以简单地做len(np.isnan(z)) 或类似的。另请注意,您会通过~np.isnan(z) 获得所有不是 NaN 的数字。
  • 实际上,他们只是在 z 列中没有数字。因此,它们被放置在散点图中,但应该以与其他具有实际 z 值的颜色不同的颜色显示。我注意到在您建议的这个散点函数中它们显示为红色(就像 z>8 一样)。也许我可以为 z>8 创建另一个类并让 'np.zeros(len(x))' 成为 NaN 值?
  • 我明白了。你说的应该可以。你也可以试试classes[np.isnan(z)] = 4。然后他们应该被分配黄色。
【解决方案2】:

根据 roadrunner66 的评论,在 Python2.7 中也可以使用的另一种方法如下:

#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt

x = np.asarray(composition)
y = np.asarray(composition)
z = np.asarray(planetary_radii)

# some stuff to let the scatter organized:
left, width = 0.1, 0.7
bottom, height = 0.1, 0.7
rect_scatter = [left, bottom, width, height]
ax_scatter = plt.axes(rect_scatter)

# definition of filters, colors, and labels
filters = [z > 8, (z <= 8) & (z > 4), (z <= 4) & (z > 2), z <= 2]
colors = ['r', 'b', 'g', 'orange', 'y']
labels = ['Radii $> 8$', r'$4 <$ Radii $\leq 8$', 
        r'$2 <$ Radii $\leq 4$', r'Radii $\leq 2$']

# filter the data and plot:
for idx, f in enumerate(filters):
    ax_scatter.scatter(x[f], y[f], 
        c=colors[idx], s=10, label=labels[idx])

ax_scatter.legend(title='Classes', loc="lower right")
plt.show()

首先确保您的数据存储在np.arrays 中。 filterscolorslabels 可以任意设置。之后,使用先前定义的过滤标准过滤数据并绘制。这里应用了指定的colorslabels

【讨论】:

    猜你喜欢
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多