首页 > 解决方案 > matplotlib 如何使用 facecolors='none' 为不同的类绘制不同的边缘颜色?

问题描述

我正在尝试制作这样的情节

在此处输入图像描述

意思是facecolors='none'

这段代码

X, y = make_circles(100, factor=.1, noise=.1)
plt.scatter(X[:, 0], X[:, 1], s=50, cmap='autumn', facecolors='none', edgecolors='r')

在此处输入图像描述

这两个类都使用红色。

这是因为当我尝试使用edgecolors=y

X, y = make_circles(100, factor=.1, noise=.1)
plt.scatter(X[:, 0], X[:, 1], s=50, cmap='autumn', facecolors='none', edgecolors=y)

我收到了这个错误

    261     # tuple color.
    262     if not np.iterable(c):
--> 263         raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
    264     if len(c) not in [3, 4]:
    265         raise ValueError("RGBA sequence should have length 3 or 4")

如何正确使用边缘颜色?

标签: pythonmatplotlib

解决方案


Edgecolors 不像 c

cmap参数将仅应用于c. 但是c会覆盖facecolors="none"所以我们不想使用它。

与参数不同c,参数edgecolors必须接收可直接解释为颜色的值,即 rgb 或 rgba 值、color_strings... 或此matplotlib 颜色页面中指定的任何格式。

您可以传递y给 cmap :

import matplotlib.pyplot as plt
cmap = plt.get_cmap("winter")
colors = cmap(y * 255) # or cmap(y.astype(float))
print(colors)
# > array([[1., 1., 0., 1.], # RGBA values
#          [1., 1., 0., 1.],
#          [1., 1., 0., 1.],
#          [1., 0., 0., 1.],
#                ...       ])
plt.scatter(X[:, 0], X[:, 1], s=50, facecolors="none", edgecolors=colors)

请注意,您必须传递 0 到 255 之间的整数或 0. 到 1. 之间的浮点数,才能沿 cmap 分布颜色。

用 cmap 绘图

您还可以从自己设计的字典中推断颜色:

color_dict = {0: "r", 1: "b"}
colors=tuple(map(color_dict.get, y))
print(colors)
# > ('b', 'b', 'b', 'r', ...)
plt.scatter(X[:, 0], X[:, 1], s=50, facecolors="none", edgecolors=colors)

用 dict 绘图

标记不像颜色

您不能在单个scatter调用中指定不同的标记,因为它只接受 a 的单个表示MarkerStyle(作为类的实例或作为字符串)。

这意味着您必须调用scatter与您想要的不同标记数一样多的次数。

此外,目前,您无法edgecolor使用+ markerstyle.

最简单的方法是按颜色屏蔽您的数据:

red_mask = y==0
print(red_mask)
# > [False, False, False, True ...]
plt.scatter(X[red_mask, 0], X[red_mask, 1], s=50, facecolors="none", edgecolors="r")
plt.scatter(X[~red_mask, 0], X[~red_mask, 1], s=50, marker="+", c="b")

使用标记样式绘制

另一种解决方案是绘制每个点,但它不太优雅 IMO :

for X_x, X_y, clas in zip(X[:, 0], X[:, 1], y) :
    if clas == 1:
        plt.scatter(X_x, X_y, c="b", marker="+")
    else:
        plt.scatter(X_x, X_y, facecolors="none", edgecolor="r", marker="o", )
# Same resulting plot

推荐阅读