パンダでプロットすると凡例にラベルが 1 つしか表示されない 質問する

パンダでプロットすると凡例にラベルが 1 つしか表示されない 質問する

2 つの Pandas DataFrame があり、これを 1 つの図にプロットしたいと考えています。IPython ノートブックを使用しています。

凡例に両方の DataFrame のラベルを表示したいのですが、今のところ後者のラベルしか表示できません。また、より合理的な方法でコードを記述する方法について提案があれば、ぜひ教えてください。私はこれらすべてに不慣れで、オブジェクト指向のプロットをあまり理解していません。

%pylab inline
import pandas as pd

#creating data

prng = pd.period_range('1/1/2011', '1/1/2012', freq='M')
var=pd.DataFrame(randn(len(prng)),index=prng,columns=['total'])
shares=pd.DataFrame(randn(len(prng)),index=index,columns=['average'])

#plotting

ax=var.total.plot(label='Variance')
ax=shares.average.plot(secondary_y=True,label='Average Age')
ax.left_ax.set_ylabel('Variance of log wages')
ax.right_ax.set_ylabel('Average age')
plt.legend(loc='upper center')
plt.title('Wage Variance and Mean Age')
plt.show()

凡例のラベルが1つ欠落しています

ベストアンサー1

これは確かに少し混乱します。これは、Matplotlib がセカンダリ軸をどのように処理するかに帰着すると思います。Pandas はおそらく、セカンダリax.twinx()軸を最初の軸に重ねるどこかを呼び出しますが、これは実際には別の軸です。したがって、別の線とラベル、および別の凡例もあります。呼び出しは、plt.legend()軸の 1 つ (アクティブな軸) にのみ適用されます。この例では、2 番目の軸です。

幸いなことに、Pandas は両方の軸を保存しているので、両方の軸からすべての線オブジェクトを取得して、.legend()自分でコマンドに渡すことができます。サンプル データは次のとおりです。

まさに同じようにプロットできます:

ax = var.total.plot(label='Variance')
ax = shares.average.plot(secondary_y=True, label='Average Age')

ax.set_ylabel('Variance of log wages')
ax.right_ax.set_ylabel('Average age')

両方の軸オブジェクトはax(left axe)と で使用できるax.right_axため、そこから線オブジェクトを取得できます。Matplotlib は.get_lines()リストを返すため、単純な加算でそれらを結合できます。

lines = ax.get_lines() + ax.right_ax.get_lines()

ライン オブジェクトには、ラベルを読み取ってコマンドに渡すために使用できるラベル プロパティがあります.legend()

ax.legend(lines, [l.get_label() for l in lines], loc='upper center')

残りの計画は次のとおりです。

ax.set_title('Wage Variance and Mean Age')
plt.show()

ここに画像の説明を入力してください

編集:

Pandas (データ) と Matplotlib (プロット) の部分をもっと厳密に分離すると混乱が少なくなるかもしれないので、Pandas の組み込みプロット (とにかく Matplotlib をラップするだけ) の使用は避けてください。

fig, ax = plt.subplots()

ax.plot(var.index.to_datetime(), var.total, 'b', label='Variance')
ax.set_ylabel('Variance of log wages')

ax2 = ax.twinx()
ax2.plot(shares.index.to_datetime(), shares.average, 'g' , label='Average Age')
ax2.set_ylabel('Average age')

lines = ax.get_lines() + ax2.get_lines()
ax.legend(lines, [line.get_label() for line in lines], loc='upper center')

ax.set_title('Wage Variance and Mean Age')
plt.show()

おすすめ記事