我有两个Pandas DataFrames,我希望在单个图中绘制。我正在使用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()
答案 0 :(得分:33)
这确实有点令人困惑。我认为这归结为Matplotlib如何处理次轴。熊猫可能会在某个地方调用ax.twinx()
,在第一个轴上叠加一个辅助轴,但这实际上是一个单独的轴。因此也有单独的线和&标签和单独的图例。调用plt.legend()
仅适用于其中一个轴(活动轴),在您的示例中是第二个轴。
.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
(左斧)和ax.right_ax
,因此您可以从中抓取线对象。 Matplotlib的.get_lines()
返回一个列表,以便您可以通过简单的添加来合并它们。
lines = ax.get_lines() + ax.right_ax.get_lines()
行对象有一个label属性,可用于读取标签并将其传递给.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()
答案 1 :(得分:3)
绘制多个系列时,默认情况下不显示图例 显示自定义图例的简单方法就是使用上次绘制的系列/数据框中的轴(我的代码来自 IPython Notebook ):
%matplotlib inline # Embed the plot
import matplotlib.pyplot as plt
...
rates[rates.MovieID <= 25].groupby('MovieID').Rating.count().plot() # blue
(rates[rates.MovieID <= 25].groupby('MovieID').Rating.median() * 1000).plot() # green
(rates[rates.MovieID <= 25][rates.RateDelta <= 10].groupby('MovieID').Rating.count() * 2000).plot() # red
ax = (rates[rates.MovieID <= 25][rates.RateDelta <= 10].groupby('MovieID').Rating.median() * 1000).plot() # cyan
ax.legend(['Popularity', 'RateMedian', 'FirstPpl', 'FirstRM'])
答案 2 :(得分:0)
您可以使用pd.concat
合并两个数据框,然后使用辅助y轴绘图:
import numpy as np # For generating random data.
import pandas as pd
# Creating data.
np.random.seed(0)
prng = pd.period_range('1/1/2011', '1/1/2012', freq='M')
var = pd.DataFrame(np.random.randn(len(prng)), index=prng, columns=['total'])
shares = pd.DataFrame(np.random.randn(len(prng)), index=prng, columns=['average'])
# Plotting.
ax = (
pd.concat([var, shares], axis=1)
.rename(columns={
'total': 'Variance of Low Wages',
'average': 'Average Age'
})
.plot(
title='Wage Variance and Mean Age',
secondary_y='Average Age')
)
ax.set_ylabel('Variance of Low Wages')
ax.right_ax.set_ylabel('Average Age', rotation=-90)