如何修改散点图图例以显示相同类型句柄的不同格式?

Posted

技术标签:

【中文标题】如何修改散点图图例以显示相同类型句柄的不同格式?【英文标题】:How to modify scatter-plot figure legend to show different formats for the same types of handles? 【发布时间】:2020-06-18 21:18:03 【问题描述】:

我正在尝试修改包含两个重叠散点图的图例。更具体地说,我想要两个图例句柄和标签:第一个句柄将包含多个点(每个点的颜色不同),而另一个句柄由一个点组成。

As per this related question,我可以修改图例句柄以显示多个点,每个点都是不同的颜色。

As per this similar question,我知道我可以更改指定句柄显示的点数。但是,这会将更改应用于图例中的所有句柄。可以只用在一个手柄上吗?

我的目标是结合这两种方法。有没有办法做到这一点?

如果不清楚,我想修改嵌入图(见下文),使Z vs X 句柄仅在相应的图例标签旁边显示一个点,而留下Y vs X句柄不变。

我制作这样一个数字的失败尝试如下:

要复制此图,可以运行以下代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerTuple, HandlerRegularPolyCollection

class ScatterHandler(HandlerRegularPolyCollection):

    def update_prop(self, legend_handle, orig_handle, legend):
        """ """
        legend._set_artist_props(legend_handle)
        legend_handle.set_clip_box(None)
        legend_handle.set_clip_path(None)

    def create_collection(self, orig_handle, sizes, offsets, transOffset):
        """ """
        p = type(orig_handle)([orig_handle.get_paths()[0]], sizes=sizes, offsets=offsets, transOffset=transOffset, cmap=orig_handle.get_cmap(), norm=orig_handle.norm)
        a = orig_handle.get_array()
        if type(a) != type(None):
            p.set_array(np.linspace(a.min(), a.max(), len(offsets)))
        else:
            self._update_prop(p, orig_handle)
        return p

x = np.arange(10)
y = np.sin(x)
z = np.cos(x)

fig, ax = plt.subplots()
hy = ax.scatter(x, y, cmap='plasma', c=y, label='Y vs X')
hz = ax.scatter(x, z, color='k', label='Z vs X')
ax.grid(color='k', linestyle=':', alpha=0.3)
fig.subplots_adjust(bottom=0.2)
handler_map = type(hz) : ScatterHandler()
fig.legend(mode='expand', ncol=2, loc='lower center', handler_map=handler_map, scatterpoints=5)

plt.show()
plt.close(fig)

我不喜欢的一个解决方案是创建两个图例 - 一个用于Z vs X,一个用于Y vs X。但是,我的实际用例涉及可选数量的句柄(可以超过两个),我不想计算每个图例框的最佳宽度/高度。还有什么办法可以解决这个问题?

【问题讨论】:

【参考方案1】:

这是一个肮脏的技巧,而不是一个优雅的解决方案,但您可以将 Z-X 图例的其他点的大小设置为 0。只需将最后两行更改为以下内容。

leg = fig.legend(mode='expand', ncol=2, loc='lower center', handler_map=handler_map, scatterpoints=5)
# The third dot of the second legend stays the same size, others are set to 0
leg.legendHandles[1].set_sizes([0,0,leg.legendHandles[1].get_sizes()[2],0,0])

结果如图。

【讨论】:

您的解决方案似乎运行良好。但是,我仍然想弄清楚为什么。运行print(leg.legendHandles[1].get_sizes()) 显示[36. 36. 36. 36. 36.]。我不明白这些对应什么,以及你为什么使用leg.legendHandles[1].get_sizes()[2]。如果你不介意,你能解释一下发生了什么吗? legendHandles[0] 对应左边的图例,legendHandles[1] 对应右边的图例。 get_sizes() 返回 5 个点中每个点的面积。我通过set_sizes[0,0, , 0,0] 将第 1、2、4、5 个点的区域设置为 0,通过leg.legendHandles[1].get_sizes()[2] 将第 3 个点设置为之前的任何值。我希望这更清楚。

以上是关于如何修改散点图图例以显示相同类型句柄的不同格式?的主要内容,如果未能解决你的问题,请参考以下文章

excel绘制散点图时,如何进行分组绘图?

R语言散点图可视化:自定义标题和标签拟合回归线lowess为散点图添加平滑拟合线修改散点图中点颜色和点符号分组散点图添加图例pairs可视化散点图矩阵ggplt2可视化lattice

绘制散点图图例不显示图例标题,但每种颜色都有 = 符号

如何将excel的一组数据既做成散点图又做成条状图,意思就是散点图和条状图在一个图里

怎么用gis做散点图显示样方

如何迭代散点图的列表并创建独特元素的图例