圖例指南
原文: Legend guide 譯者: 飛龍 協定: CC BY-NC-SA 4.0
此圖例指南是
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)
文檔
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'
圖例的位置。 可能的代碼是:
位置字元串 | 位置代碼 |
---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
或者,可以是一個二進制組,提供圖例的距離左下角的
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()
中獲得的預設處理器字典。