首页 > 解决方案 > Matplotlib:绘制一条带有开放标记的线,其中该线在标记内不可见

问题描述

我有一个散点图,显示了一个数据集,其中的符号根据某种色标着色。我想通过在它们周围画一个开放的圆圈并用一条线连接它们来突出其中的几个点。换句话说,在一个非常简化的示例中,我希望结果如下所示:

带有彩色数据和几个突出显示点的散点图,由一条线连接,其中符号内的线段隐藏在视图之外.

我可以使用以下代码制作一个看起来有点像的情节:

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(5,5))

X, Y = np.meshgrid(np.arange(10), np.arange(10))
Z = X**2 + Y**2

plt.scatter(X,Y,c=Z, s=300, cmap='viridis_r')

plt.plot([1, 4, 7], [7, 1, 4], 'k-o', linewidth=3, 
         markersize=14, markerfacecolor='none', markeredgewidth=2, 
        )

但是,结果如下所示:

带有彩色数据和几个突出显示点的散点图,由一条线连接.

我想要的是让标记符号的线段从视图中隐藏。这是因为我有兴趣将注意力吸引到特定的数据点上,并且不想部分地将它们隐藏起来。

解决方法是:

  1. 复制我要突出显示的数据点,并用与标记隐藏的原始符号完全相同的颜色填充标记。这并不令人满意,因为(a)我并不总是可以访问数据,只能访问输出图形或轴实例,并且(b)在半透明符号的情况下我不知道如何做到这一点,在我的实际数据集中就是这种情况。
  2. 手动计算调整后的坐标以使连接线仅到达标记的边缘。这似乎也很不令人满意(而且我不知道该怎么做,因为轴和符号的坐标系不会相同)。

我的问题是:最好的方法是什么?有没有比上面的选项 1 和 2 更好的方法,如果没有,最好的方法是什么?如前所述,对于 1,我预见到透明度问题(我正在使用),对于 2,我预见到坐标系问题,例如在放大或缩小的情况下等。

(在我的示例中,我有点困惑的另一个小观察:plt.plot并且plt.scatter似乎没有在完全相同的位置绘制东西(参见此图)并且尺寸定义不一致)

标签: pythonmatplotlibplot

解决方案


您想要获得透明(开放)圆,定位在数据坐标中,但半径以点为单位。您想将圆圈相互连接,而不是中心点。这意味着您不能使用法线。相反,几个ConnectionPatches 可以提供帮助。您可以将它们缩小一半的标记大小,以便它们接触圆圈的边界。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch

fig, ax = plt.subplots(figsize=(5,5))

X, Y = np.meshgrid(np.arange(10), np.arange(10))
Z = X**2 + Y**2

ax.scatter(X,Y,c=Z, s=300, cmap='viridis_r')

xc = [1, 4, 7]
yc = [7, 1, 4]

ax.plot(xc, yc, linewidth=0, marker="o", color="black",
         markersize=np.sqrt(300), markerfacecolor='none', markeredgewidth=3)

for i in range(len(xc)-1):
    cp = ConnectionPatch((xc[i],yc[i]), (xc[i+1], yc[i+1]), 
                         coordsA='data', coordsB='data', axesA=ax, axesB=ax,
                         shrinkA=np.sqrt(300)/2, shrinkB=np.sqrt(300)/2,
                         linewidth=2)
    ax.add_patch(cp)

plt.show()

在此处输入图像描述


推荐阅读