web-dev-qa-db-ja.com

matplotlib凡例の項目の順序はどのように決定されますか?

必要があるとは思わないときに、凡例のアイテムを並べ替える必要があります。私が試します:

from pylab import *
clf()
ax=gca()
ht=ax.add_patch(Rectangle((1,1),1,1,color='r',label='Top',alpha=.01))
h1=ax.bar(1,2,label='Middle')
hb=ax.add_patch(Rectangle((1,1),1,1,color='k',label='Bottom',alpha=.01))
legend()
show()

そして、Middleの上のBottomになります。正しい注文を取得するにはどうすればよいですか?作成順序によって決定されていませんか?

Code results in the wrong legend item order

更新:次を使用して注文を強制できます。これが最も簡単な方法かもしれませんが、それは厄介なようです。問題は、元の順序を決定するものですか?

hh=[ht,h1,hb]
legend([ht,h1.patches[0],hb],[H.get_label() for H in hh])
48
CPBL

順序は決定的ですが、プライベートの内臓の一部はいつでも変更できます。コードを参照してください hereself.*要素は追加されたアーティストのリストです。ハンドルリストは最初にタイプでソートされ、次に追加された順序でソートされます。

凡例の要素の順序を明示的に制御する場合は、編集で行ったようにハンドラーとラベルのリストを組み立てます。

11
tacaswell

凡例のエントリを並べ替える簡単なスニペットを次に示します。たとえば、次のようなラベルがプロット要素に既に追加されていることを前提としています。

ax.plot(..., label='label1')
ax.plot(..., label='label2')

そして、メインビット:

handles, labels = ax.get_legend_handles_labels()
# sort both labels and handles by labels
labels, handles = Zip(*sorted(Zip(labels, handles), key=lambda t: t[0]))
ax.legend(handles, labels)

これは http://matplotlib.org/users/legend_guide.html にリストされているコードからの単純な適応です。

62
kevin

他の一部のアスワーとは若干異なります。リストorderは、凡例項目の数と同じ長さである必要があり、新しい順序を手動で指定します。

handles, labels = plt.gca().get_legend_handles_labels()
order = [0,2,1]
plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
23
Ian Hincks

次の関数は、凡例のハンドルとラベルを探し、指定されたリスト(order)に従って並べ替え、または部分的に並べ替えます。

#  Returns Tuple of handles, labels for axis ax, after reordering them to conform to the label order `order`, and if unique is True, after removing entries with duplicate labels.
def reorderLegend(ax=None,order=None,unique=False):
    if ax is None: ax=plt.gca()
    handles, labels = ax.get_legend_handles_labels()
    labels, handles = Zip(*sorted(Zip(labels, handles), key=lambda t: t[0])) # sort both labels and handles by labels
    if order is not None: # Sort according to a given list (not necessarily complete)
        keys=dict(Zip(order,range(len(order))))
        labels, handles = Zip(*sorted(Zip(labels, handles), key=lambda t,keys=keys: keys.get(t[0],np.inf)))
    if unique:  labels, handles= Zip(*unique_everseen(Zip(labels,handles), key = labels)) # Keep only the first of each handle
    ax.legend(handles, labels)
    return(handles, labels)


def unique_everseen(seq, key=None):
    seen = set()
    seen_add = seen.add
    return [x for x,k in Zip(seq,key) if not (k in seen or seen_add(k))]

更新された形式の関数はcpblUtilities.mathgraph at https://gitlab.com/cpbl/cpblUtilities/blob/master/mathgraph.py

引用:Kevin(このページ)およびMarkus Jarderot( 順序を維持しながらリストから重複を削除するにはどうすればよいですか? )。

1
CPBL