如何修改散点图图例以显示相同类型手柄的不同格式?
How to modify scatter-plot figure legend to show different formats for the same types of handles?
我正在尝试修改包含两个重叠散点图的图形的图例。更具体地说,我想要两个图例手柄和标签:第一个手柄将包含多个点(每个颜色不同),而另一个手柄由一个点组成。
,我可以修改图例手柄以显示多个点,每个点都是不同的颜色。
As per this similar question,我知道我可以更改指定句柄显示的点数。但是,这会将更改应用于图例中的所有句柄。可以只适用于一个手柄吗?
我的目标是结合这两种方法。有办法吗?
如果不清楚,我想修改嵌入的图形(见下文),使得 Z vs X
handle 在相应的图例标签旁边只显示一个点,同时保持 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
。但是,我的实际用例涉及可选数量的句柄(可以超过两个),我宁愿不必计算每个图例框的最佳 width/height。还有什么办法可以解决这个问题?
这是一个肮脏的技巧,不是一个优雅的解决方案,但您可以将 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])
结果如图
我正在尝试修改包含两个重叠散点图的图形的图例。更具体地说,我想要两个图例手柄和标签:第一个手柄将包含多个点(每个颜色不同),而另一个手柄由一个点组成。
As per this similar question,我知道我可以更改指定句柄显示的点数。但是,这会将更改应用于图例中的所有句柄。可以只适用于一个手柄吗?
我的目标是结合这两种方法。有办法吗?
如果不清楚,我想修改嵌入的图形(见下文),使得 Z vs X
handle 在相应的图例标签旁边只显示一个点,同时保持 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
。但是,我的实际用例涉及可选数量的句柄(可以超过两个),我宁愿不必计算每个图例框的最佳 width/height。还有什么办法可以解决这个问题?
这是一个肮脏的技巧,不是一个优雅的解决方案,但您可以将 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])
结果如图