【发布时间】:2020-08-03 19:26:26
【问题描述】:
我必须在 Matplotlib 中绘制一个数量,该数量是各种贡献的 sum。
我想通过将各种贡献列为主要图例条目的子元素来在情节图例中突出这一事实。
我想获得的结果草图可以在下面的图片中找到。请注意,我不一定要完全实现所描绘的图例,而只是类似的东西。
【问题讨论】:
标签: python matplotlib legend
我必须在 Matplotlib 中绘制一个数量,该数量是各种贡献的 sum。
我想通过将各种贡献列为主要图例条目的子元素来在情节图例中突出这一事实。
我想获得的结果草图可以在下面的图片中找到。请注意,我不一定要完全实现所描绘的图例,而只是类似的东西。
【问题讨论】:
标签: python matplotlib legend
您可以尝试为您的人物创建两个单独的图例。当然,这是一个技巧,而不是图例对象的直接功能,因为在 matplotlib 中似乎没有实现您需要的功能。但是使用 bbox 中的数字和字体大小,您可以很好地自定义它。
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.0, 1, 0.01)
x1 = np.sin(2*np.pi*x)
x2 = np.sin(2*np.pi*x+1)
x3 = np.sin(2*np.pi*x+2)
fig, ax = plt.subplots()
f1, = ax.plot(x1, 'r', lw=4)
f2, = ax.plot(x2, 'k', lw=2)
f3, = ax.plot(x3, 'b', lw=2)
legend1 = plt.legend([f1], ["Main legend"], fontsize=12, loc=3, bbox_to_anchor=(0,0.1,0,0), frameon=False)
legend2 = plt.legend((f2, f3), ('sublegend 1', 'sublegend 2'), fontsize=9,
loc=3, bbox_to_anchor=(0.05,0,0,0), frameon=False)
plt.gca().add_artist(legend1)
plt.show()
编辑:
好吧,如果我们插入 2 个图例,为什么不在更大的图中插入一个全新的图作为插图,专用于图例,在其中您可以绘制和写任何您喜欢的东西?诚然,这是一项艰巨的工作,您必须设计内部的每条线,包括精确的位置坐标。但这是我能想到的做你想做的事的方式:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.0, 1, 0.01)
x1 = np.sin(2*np.pi*x)
x2 = np.sin(2*np.pi*x+1)
x3 = np.sin(2*np.pi*x+2)
fig, ax = plt.subplots()
f1, = ax.plot(x1, 'r', lw=4)
f2, = ax.plot(x2, 'k', lw=2)
f3, = ax.plot(x3, 'b', lw=2)
## set all lines for inner figure
yline1 = np.array([-0.15, -0.15])
line1 = np.array([2, 10])
yline2 = np.array([3, 0])
line2 = np.array([4, 4])
yline3 = np.array([1.5, 1.5])
line3 = np.array([4, 6])
yline4 = np.array([1.5, 1.5])
line4 = np.array([7, 10])
yline5 = np.array([3, 3])
line5 = np.array([4, 6])
yline6 = np.array([3, 3])
line6 = np.array([7, 10])
## inset figure
axin1 = ax.inset_axes([2.5, -1, 30, 0.5], transform=ax.transData) #
## plot all lines
axin1.plot(line1, yline1, linewidth=4, c='r')
axin1.plot(line2, yline2, 'k', lw=1)
axin1.plot(line3, yline3, 'k', lw=1)
axin1.plot(line4, yline4, 'b', lw=3)
axin1.plot(line5, yline5, 'k', lw=1)
axin1.plot(line6, yline6, 'k', lw=3)
## text
axin1.text(12, 0, 'MAIN', fontsize=12)
axin1.text(12, 1.7, 'Subtext 1', fontsize=10)
axin1.text(12, 3.2, 'Subtext 2', fontsize=10)
## adjust
axin1.set_ylim([4, -1])
axin1.set_xlim([0, 27])
axin1.set_xticklabels('')
axin1.set_yticklabels('')
【讨论】:
我在图例中查找了一个自定义示例,但没有看到任何降低级别的迹象。您只需排列图例中的对象即可。我以颜色和标记的形式创建了呈现图像的层次结构。官方reference已定制。这具有消除以特殊方式仅注释图例的需要的效果。
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerLineCollection, HandlerTuple
fig, ax1 = plt.subplots(1, 1, constrained_layout=True)
params = {'legend.fontsize': 16,
'legend.handlelength': 3}
plt.rcParams.update(params)
x = np.linspace(0, np.pi, 25)
xx = np.linspace(0, 2*np.pi, 25)
xxx = np.linspace(0, 3*np.pi, 25)
p1, = ax1.plot(x, np.sin(x), lw=5, c='r')
p2, = ax1.plot(x, np.sin(xx), 'm-d', c='g')
p3, = ax1.plot(x, np.sin(xxx), 'm-s', c='b')
# Assign two of the handles to the same legend entry by putting them in a tuple
# and using a generic handler map (which would be used for any additional
# tuples of handles like (p1, p2)).
l = ax1.legend([p1, (p1, p2), (p1, p3)], ['Legend entry', 'Contribution 1', 'Contribution 2'], scatterpoints=1,
numpoints=1, markerscale=1.3, handler_map={tuple: HandlerTuple(ndivide=None, pad=1.0)})
plt.show()
【讨论】: