web-dev-qa-db-ja.com

凡例のmatplotlib繰り返しラベルを停止

これは非常に単純化された例です。

xvalues = [2,3,4,6]

for x in xvalues:
    plt.axvline(x,color='b',label='xvalues')

plt.legend()

凡例では、「xvalues」が青い線で4回表示されます。これを修正するよりエレガントな方法は次のものよりもありますか?

for i,x in enumerate(xvalues):
    if not i:
        plt.axvline(x,color='b',label='xvalues')
    else:
        plt.axvline(x,color='b')
49
Anake

legendは、引数として軸ハンドルとラベルのリストを取ります。デフォルトはplt.gca().get_legend_handles_labels()です。 legendを呼び出すときに、重複するラベルを削除できます。次に例を示します。

from collections import OrderedDict
import matplotlib.pyplot as plt

handles, labels = plt.gca().get_legend_handles_labels()
by_label = OrderedDict(Zip(labels, handles))
plt.legend(by_label.values(), by_label.keys())
83
ecatmur
handles, labels = ax.get_legend_handles_labels()
handle_list, label_list = [], []
for handle, label in Zip(handles, labels):
    if label not in label_list:
        handle_list.append(handle)
        label_list.append(label)
plt.legend(handle_list, label_list)
6
Matthew Bourque

これらのコードスニペットは個人的には機能しませんでした。 2つの異なるグループを2つの異なる色でプロットしました。凡例には、2つの赤いマーカーと2つの青いマーカーが表示されますが、色ごとに1つしか見たくありませんでした。私がうまくいったことの簡略版を貼り付けます:

インポートステートメント

import matplotlib.pyplot as plt

from matplotlib.legend_handler import HandlerLine2D

データをプロットする

points_grp, = plt.plot(x[grp_idx], y[grp_idx], color=c.c[1], marker=m, ms=4, lw=0, label=leglab[1])        
points_ctrl, = plt.plot(x[ctrl_idx], y[ctrl_idx], color=c.c[0], marker=m, ms=4, lw=0, label=leglab[0])

凡例を追加

points_dict = {points_grp: HandlerLine2D(numpoints=1),points_ctrl: HandlerLine2D(numpoints=1)}
leg = ax.legend(fontsize=12, loc='upper left', bbox_to_anchor=(1, 1.03),handler_map=points_dict)
1

これが「エレガント」と見なされるかどうかはわかりませんが、最初の使用後に"_nolegend_"に設定される変数をラベルに設定できます。

my_label = "xvalues"
xvalues = [2,3,4,6]

for x in xvalues:
    plt.axvline(x, color='b', label=my_label)
    my_label = "_nolegend_"

plt.legend()

これは、複数のラベルを配置する必要がある場合、ラベルの辞書を使用して一般化できます。

my_labels = {"x1" : "x1values", "x2" : "x2values"}
x1values = [1, 3, 5]
x2values = [2, 4, 6]

for x in x1values:
    plt.axvline(x, color='b', label=my_labels["x1"])
    my_labels["x1"] = "_nolegend_"
for x in x2values:
    plt.axvline(x, color='r', label=my_labels["x2"])
    my_labels["x2"] = "_nolegend_"

plt.legend()

Figure with 2 different labels

https://stackoverflow.com/a/19386045/1878788 に触発された回答)

1
bli

回答に基づいて https://stackoverflow.com/a/13589144/9132798 および https://stackoverflow.com/a/19386045/9132798plt.gca().get_legend_handles_labels()[1]は名前のリストを提供します。ループプロット中にラベルが既にリストにあるかどうかを確認できます(label= name[i] if name[i] not in plt.gca().get_legend_handles_labels()[1] else '')。指定された例では、このソリューションは次のようになります。

import matplotlib.pyplot as plt

xvalues = [2,3,4,6]

for x in xvalues:
    plt.axvline(x,color='b',\
    label= 'xvalues' if 'xvalues' \
            not in plt.gca().get_legend_handles_labels()[1] else '')

plt.legend()

これは https://stackoverflow.com/a/13589144/9132798 よりもはるかに短く、 https://stackoverflow.com/a/19386045/9132798 よりも柔軟ですループ内のプロット関数を個別に使用することができます。ただし、多くのサイクルでは、おそらく https://stackoverflow.com/a/13589144/9132798 よりも遅くなります。

0
Tobias Wegener