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
これは確かに少し混乱します。これは、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()