python - savefig - plot style pandas
La leyenda solo muestra una etiqueta al trazar con pandas (3)
Cuando se trazan varias series, la leyenda no se muestra de forma predeterminada.
La manera fácil de mostrar leyendas personalizadas es simplemente usar el eje de las últimas series / marcos de datos trazados (mi código de 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''])
Tengo dos Pandas DataFrames que espero trazar en una sola figura. Estoy usando el cuaderno de IPython.
Me gustaría que la leyenda muestre la etiqueta para los dos DataFrames, pero hasta ahora he podido conseguir solo la última para mostrar. También se agradecería cualquier sugerencia sobre cómo escribir el código de una manera más sensata. Soy nuevo en todo esto y no entiendo realmente la trama orientada a objetos.
%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()
Esto es de hecho un poco confuso. Creo que se reduce a cómo Matplotlib maneja los ejes secundarios. Las pandas probablemente llaman a ax.twinx()
algún lugar que superpone un eje secundario al primero, pero en realidad es un eje separado. Por lo tanto, también con líneas y etiquetas separadas y una leyenda separada. Llamar a plt.legend()
solo se aplica a uno de los ejes (el activo) que en su ejemplo es el segundo eje.
Afortunadamente, los pandas almacenan ambos ejes, por lo que puedes tomar todos los objetos de línea de ambos y pasarlos al comando .legend()
. Dados los datos de su ejemplo:
Puedes trazar exactamente como lo hiciste:
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'')
Los objetos de ambos ejes están disponibles con ax
(eje izquierdo) y ax.right_ax
, por lo que puede agarrar los objetos de línea de ellos. Los .get_lines()
Matplotlib devuelven una lista para que pueda combinarlos por simple adición.
lines = ax.get_lines() + ax.right_ax.get_lines()
Los objetos de línea tienen una propiedad de etiqueta que se puede usar para leer y pasar la etiqueta al comando .legend()
.
ax.legend(lines, [l.get_label() for l in lines], loc=''upper center'')
Y el resto de la conspiración:
ax.set_title(''Wage Variance and Mean Age'')
plt.show()
editar:
Podría ser menos confuso si separas las partes de Pandas (datos) y Matplotlib (trazado) de manera más estricta, así que evita el uso del trazado de Pandas (que solo envuelve Matplotlib de todos modos):
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()
Puede usar pd.concat
para fusionar los dos marcos de datos y luego trazar está utilizando un eje y secundario:
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)