圖例指南
原文:Legend guide
譯者:飛龍
此圖例指南是legend()
中可用文檔的擴展 - 請在繼續閱讀本指南之前確保你熟悉該文檔(見篇尾)的內容。
本指南使用一些常見術語,為了清楚起見,這些術語在此處進行說明:
圖例條目
圖例由一個或多個圖例條目組成。 一個條目由一個鍵和一個標簽組成。
圖例鍵
每個圖例標簽左側的彩色/圖案標記。
圖例標簽
描述由鍵表示的句柄的文本。
圖例句柄
用于在圖例中生成適當條目的原始對象。
控制圖例條目
不帶參數調用legend()
會自動獲取圖例句柄及其相關標簽。 此函數等同于:
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)
get_legend_handles_labels()
函數返回軸域上存在的句柄/藝術家的列表,這些句柄/藝術家可以用于為結果圖例生成條目 - 但值得注意的是,并非所有藝術家都可以添加到圖例中, 這種情況下會創建『代理』(請參閱特地為添加到圖例創建藝術家(也稱為代理藝術家),來了解更多詳細信息)。
為了完全控制要添加到圖例的內容,通常將適當的句柄直接傳遞給legend()
:
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
plt.legend(handles=[line_up, line_down])
在某些情況下,不可能設置句柄的標簽,因此可以將標簽列表傳遞給legend()
:
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
plt.legend([line_up, line_down], ['Line Up', 'Line Down'])
特地為添加到圖例創建藝術家(也稱為代理藝術家)
并非所有的句柄都可以自動轉換為圖例條目,因此通常需要創建一個可轉換的藝術家。 圖例句柄不必存在于被用到的圖像或軸域上。
假設我們想創建一個圖例,其中有一些數據表示為紅色:
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
red_patch = mpatches.Patch(color='red', label='The red data')
plt.legend(handles=[red_patch])
plt.show()
除了創建一個色塊之外,有許多受支持的圖例句柄,我們可以創建一個帶有標記的線條:
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
blue_line = mlines.Line2D([], [], color='blue', marker='*',
markersize=15, label='Blue stars')
plt.legend(handles=[blue_line])
plt.show()
圖例位置
圖例的位置可以通過關鍵字參數loc
指定。 詳細信息請參閱legend()
的文檔。
bbox_to_anchor
關鍵字可讓用戶手動控制圖例布局。 例如,如果你希望軸域圖例位于圖像的右上角而不是軸域的邊角,則只需指定角的位置以及該位置的坐標系:
plt.legend(bbox_to_anchor=(1, 1),
bbox_transform=plt.gcf().transFigure)
自定義圖例位置的更多示例:
import matplotlib.pyplot as plt
plt.subplot(211)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# 將圖例放到這個子圖上方,
# 擴展自身來完全利用提供的邊界框。
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
ncol=2, mode="expand", borderaxespad=0.)
plt.subplot(223)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# 將圖例放到這個小型子圖的右側
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
相同軸域內的多個圖例
有時,在多個圖例之間分割圖例條目會更加清晰。 雖然直覺上的做法可能是多次調用legend()
函數,但你會發現軸域上只存在一個圖例。 這樣做是為了可以重復調用legend()
,將圖例更新為軸域上的最新句柄,因此要保留舊的圖例實例,我們必須將它們手動添加到軸域中:
import matplotlib.pyplot as plt
line1, = plt.plot([1,2,3], label="Line 1", linestyle='--')
line2, = plt.plot([3,2,1], label="Line 2", linewidth=4)
# 為第一個線條創建圖例
first_legend = plt.legend(handles=[line1], loc=1)
# 手動將圖例添加到當前軸域
ax = plt.gca().add_artist(first_legend)
# 為第二個線條創建另一個圖例
plt.legend(handles=[line2], loc=4)
plt.show()
圖例處理器
為了創建圖例條目,將句柄作為參數提供給適當的HandlerBase
子類。 處理器子類的選擇由以下規則確定:
- 使用
handler_map
關鍵字中的值更新get_legend_handler_map()
。 - 檢查句柄是否在新創建的
handler_map
中。 - 檢查句柄的類型是否在新創建的
handler_map
中。 - 檢查句柄的
mro
中的任何類型是否在新創建的handler_map
中。
處于完整性,這個邏輯大多在get_legend_handler()
中實現。
所有這些靈活性意味著我們可以使用一些必要的鉤子,為我們自己的圖例鍵類型實現自定義處理器。
使用自定義處理器的最簡單的例子是,實例化一個現有的HandlerBase
子類。 為了簡單起見,讓我們選擇matplotlib.legend_handler.HandlerLine2D
,它接受numpoints
參數(出于便利,注意numpoints
是legend()
函數上的一個關鍵字)。 然后我們可以將實例的字典作為關鍵字handler_map
傳給legend
。
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerLine2D
line1, = plt.plot([3,2,1], marker='o', label='Line 1')
line2, = plt.plot([1,2,3], marker='o', label='Line 2')
plt.legend(handler_map={line1: HandlerLine2D(numpoints=4)})
如你所見,Line 1
現在有 4 個標記點,Line 2
有兩個(默認值)。 嘗試上面的代碼,只需將字典的鍵從line1
更改為type(line)。 注意現在兩個
Line2D`實例都擁有了 4 個標記。
除了用于復雜的繪圖類型的處理器,如誤差條,莖葉圖和直方圖,默認的handler_map
有一個特殊的元組處理器(HandlerTuple
),它簡單地在頂部一一繪制給定元組中每個項目的句柄。 以下示例演示如何將兩個圖例的鍵相互疊加:
import matplotlib.pyplot as plt
from numpy.random import randn
z = randn(10)
red_dot, = plt.plot(z, "ro", markersize=15)
# 將白色十字放置在一些數據上
white_cross, = plt.plot(z[:5], "w+", markeredgewidth=3, markersize=15)
plt.legend([red_dot, (red_dot, white_cross)], ["Attr A", "Attr A+B"])
實現自定義圖例處理器
可以實現自定義處理器,將任何句柄轉換為圖例的鍵(句柄不必要是matplotlib
artist)。 處理器必須實現legend_artist
方法,該方法為要使用的圖例返回單個藝術家。 有關legend_artist
的詳細信息,請參閱legend_artist()
。
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
class AnyObject(object):
pass
class AnyObjectHandler(object):
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
x0, y0 = handlebox.xdescent, handlebox.ydescent
width, height = handlebox.width, handlebox.height
patch = mpatches.Rectangle([x0, y0], width, height, facecolor='red',
edgecolor='black', hatch='xx', lw=3,
transform=handlebox.get_transform())
handlebox.add_artist(patch)
return patch
plt.legend([AnyObject()], ['My first handler'],
handler_map={AnyObject: AnyObjectHandler()})
或者,如果我們想要接受全局的AnyObject
實例,而不想一直手動設置handler_map
關鍵字,我們可以注冊新的處理器:
from matplotlib.legend import Legend
Legend.update_default_handler_map({AnyObject: AnyObjectHandler()})
雖然這里的功能十分清楚,請記住,有很多已實現的處理器,你想實現的目標可能易于使用現有的類實現。 例如,要生成橢圓的圖例鍵,而不是矩形鍵:
from matplotlib.legend_handler import HandlerPatch
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
class HandlerEllipse(HandlerPatch):
def create_artists(self, legend, orig_handle,
xdescent, ydescent, width, height, fontsize, trans):
center = 0.5 * width - 0.5 * xdescent, 0.5 * height - 0.5 * ydescent
p = mpatches.Ellipse(xy=center, width=width + xdescent,
height=height + ydescent)
self.update_prop(p, orig_handle, legend)
p.set_transform(trans)
return [p]
c = mpatches.Circle((0.5, 0.5), 0.25, facecolor="green",
edgecolor="red", linewidth=3)
plt.gca().add_patch(c)
plt.legend([c], ["An ellipse, not a rectangle"],
handler_map={mpatches.Circle: HandlerEllipse()})
使用圖例的現有示例
這里是一個不太詳盡的示例列表,涉及以各種方式使用的圖例:
lines_bars_and_markers
示例代碼:scatter_with_legend.py
- API 示例代碼:
legend_demo.py
pylab_examples
示例代碼:contourf_hatching.py
pylab_examples
示例代碼:figlegend_demo.py
pylab_examples
示例代碼:finance_work2.py
pylab_examples
示例代碼:scatter_symbol.py
matplotlib.pyplot.legend(*args, **kwargs)
文檔
在軸域上放置一個圖例。
為了為軸域上已經存在的線條(例如通過繪圖)制作圖例,只需使用字符串的可迭代對象(每個圖例條目對應一個字符串)調用此函數。 例如:
ax.plot([1, 2, 3])
ax.legend(['A simple line'])
但是,為了使『標簽』和圖例元素實例保持一致,最好在藝術家創建時指定標簽,或者通過調用藝術家的set_label()
方法:
line, = ax.plot([1, 2, 3], label='Inline label')
# 通過調用該方法覆寫標簽
line.set_label('Label via method')
ax.legend()
通過定義以下劃線開頭的標簽,可以從圖例元素自動選擇中排除特定線條。 這對于所有藝術家都是默認的,因此不帶任何參數調用legend()
,并且沒有手動設置標簽會導致沒有繪制圖例。
為了完全控制哪些藝術家擁有圖例條目,可以傳遞擁有圖例的藝術家的可迭代對象,然后是相應圖例標簽的可迭代對象:
legend((line1, line2, line3), ('label1', 'label2', 'label3'))
參數
loc
:整數、字符串或者浮點偶對,默認為'upper right'
。
圖例的位置。 可能的代碼是:
位置字符串 | 位置代碼 |
---|---|
'best' |
0 |
'upper right' |
1 |
'upper left' |
2 |
'lower left' |
3 |
'lower right' |
4 |
'right' |
5 |
'center left' |
6 |
'center right' |
7 |
'lower center' |
8 |
'upper center' |
9 |
'center' |
10 |
或者,可以是一個二元組,提供圖例的距離左下角的x, y
坐標(在這種情況下,bbox_to_anchor
將被忽略)。
bbox_to_anchor
:matplotlib.transforms.BboxBase
示例或者浮點元組。
在bbox_transform
坐標(默認軸域坐標)中為圖例指定任意位置。
例如,要將圖例的右上角放在軸域中心,可以使用以下關鍵字:
loc='upper right', bbox_to_anchor=(0.5, 0.5)
ncol
:整數。
圖例的列數,默認為 1。
prop
:None
、matplotlib.font_manager.FontProperties
或者字典。
圖例的字體屬性,如果為None
(默認),會使用當前的matplotlib.rcParams
。
fontsize
:整數、浮點或者{‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’}
。
控制圖例的字體大小。 如果值為數字,則大小將為絕對字體大小(以磅為單位)。 字符串值相對于當前默認字體大小。 此參數僅在未指定prop
的情況下使用。
numpoints
:None
或者整數。
為線條/matplotlib.lines.Line2D
創建圖例條目時,圖例中的標記點數。 默認值為None
,它將從legend.numpoints
rcParam
中獲取值。
scatterpoints
:None
或者整數。
為散點圖/matplotlib.collections.PathCollection
創建圖例條目時,圖例中的標記點數。 默認值為None
,它將從legend.scatterpoints
rcParam
中獲取值。
scatteryoffsets
:浮點的可迭代對象。
為散點圖圖例條目創建的標記的垂直偏移量(相對于字體大小)。 0.0 是在圖例文本的底部,1.0 是在頂部。 為了將所有標記繪制在相同的高度,請設置為[0.5]
。 默認值為[0.375,0.5,0.3125]
。
markerscale
:None
、整數或者浮點。
圖例標記對于原始繪制的標記的相對大小。 默認值為None
,它將從legend.markerscale
rcParam
中獲取值。
markerfirst
: [ True | False ]
如果為True
,則圖例標記位于圖例標簽的左側,如果為False
,圖例標記位于圖例標簽的右側。
frameon
:None
或布爾值
控制是否應在圖例周圍繪制框架。 默認值為None
,它將從legend.frameon
rcParam
中獲取值。
fancybox
:None
或布爾值
控制是否應在構成圖例背景的FancyBboxPatch
周圍啟用圓邊。 默認值為None
,它將從legend.fancybox
rcParam
中獲取值。
shadow
:None
或布爾值
控制是否在圖例后面畫一個陰影。 默認值為None
,它將從legend.shadow
rcParam
中獲取值。
framealpha
:None
或浮點
控制圖例框架的 Alpha 透明度。 默認值為None
,它將從legend.framealpha
rcParam
中獲取值。
mode
:{"expand", None}
如果mode
設置為"expand"
,圖例將水平擴展來填充軸域區域(如果定義圖例的大小,則為bbox_to_anchor
)。
bbox_transform
:None
或者matplotlib.transforms.Transform
邊界框的變換(bbox_to_anchor
)。 對于None
值(默認),將使用Axes
的transAxes
變換。
title
:字符串或者None
圖例的標題,默認沒有標題(None
)。
borderpad
:浮點或None
圖例邊框的內邊距。 以字體大小為單位度量。 默認值為None
,它將從legend.borderpad
rcParam
中獲取值。
labelspacing
:浮點或None
圖例條目之間的垂直間距。 以字體大小為單位度量。 默認值為None
,它將從legend.labelspacing
rcParam
中獲取值。
handlelength
:浮點或None
圖例句柄的長度。 以字體大小為單位度量。 默認值為None
,它將從legend.handlelength
rcParam
取值。
handletextpad
:浮點或None
圖例句柄和文本之間的間距。 以字體大小為單位度量。 默認值為None
,它將從legend.handletextpad
rcParam
中獲取值。
borderaxespad
:浮點或None
軸和圖例邊框之間的間距。 以字體大小為單位度量。 默認值為None
,它將從legend.borderaxespad
rcParam
中獲取值。
columnspacing
:浮點或None
列間距。以字體大小為單位度量。 默認值為None
,它將從legend.columnspacing
rcParam
中獲取值。
handler_map
:字典或None
自定義字典,用于將實例或類型映射到圖例處理器。 這個handler_map
會更新在matplotlib.legend.Legend.get_legend_handler_map()
中獲得的默認處理器字典。