Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 如何修改散点图图例以显示相同类型手柄的不同格式?_Python 3.x_Matplotlib_Plot_Legend_Scatter Plot - Fatal编程技术网

Python 3.x 如何修改散点图图例以显示相同类型手柄的不同格式?

Python 3.x 如何修改散点图图例以显示相同类型手柄的不同格式?,python-3.x,matplotlib,plot,legend,scatter-plot,Python 3.x,Matplotlib,Plot,Legend,Scatter Plot,我试图修改包含两个重叠散点图的图形图例。更具体地说,我需要两个图例控制柄和标签:第一个控制柄将包含多个点(每个点的颜色不同),而另一个控制柄由单个点组成 ,我可以修改图例控制柄以显示多个点,每个点具有不同的颜色 ,我知道我可以更改指定句柄显示的点数。但是,这会将更改应用于图例中的所有控制柄。它只能应用于一个手柄吗 我的目标是将这两种方法结合起来。有办法做到这一点吗 如果不清楚,我想修改嵌入的图形(见下文),使Z vs X句柄仅显示对应图例标签旁边的一个点,同时保持Y vs X句柄不变。 我试图得

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

,我可以修改图例控制柄以显示多个点,每个点具有不同的颜色

,我知道我可以更改指定句柄显示的点数。但是,这会将更改应用于图例中的所有控制柄。它只能应用于一个手柄吗

我的目标是将这两种方法结合起来。有办法做到这一点吗

如果不清楚,我想修改嵌入的图形(见下文),使
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
。但是,我的实际用例涉及可选数量的句柄(可以超过两个),我更希望不必计算每个图例框的最佳宽度/高度。还有什么方法可以解决这个问题呢?

这是一个肮脏的把戏,不是一个优雅的解决方案,但您可以将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.legendholds[1].get_size())
显示
[36.36.36.36.]
。我不明白这些对应于什么,以及为什么使用
leg.legendholds[1]。get_size()[2]
。如果你不介意的话,你能解释一下发生了什么吗?
legendholds[0]
对应于左边的图例,而
legendholds[1]
对应于右边的图例
get_size()
返回5个点中每个点的面积。我通过
set_size[0,0,0,0]
将1,2,4,5点的区域设置为0,并通过
leg.legendholds[1]将第三个点的区域设置为之前的任何值。get_size()[2]
。我希望这更清楚。