Inconsistencia al establecer el tamaño de la figura usando el método de trazado de pandas

Estoy tratando de usar la conveniencia del método de trazado de un dataframe de pandas mientras ajuste el tamaño de la figura producida. (Estoy guardando las cifras para archivar y también las muestro en línea en un cuaderno Jupyter). Encontré que el método a continuación es exitoso la mayor parte del tiempo, excepto cuando trazo dos líneas en el mismo gráfico, luego la cifra vuelve al tamaño predeterminado.

Sospecho que esto podría deberse a las diferencias entre la ttwig de una serie y la ttwig de un dataframe.

Código de ejemplo de instalación:

data = { 'A': 90 + np.random.randn(366), 'B': 85 + np.random.randn(366) } date_range = pd.date_range('2016-01-01', '2016-12-31') index = pd.Index(date_range, name='Date') df = pd.DataFrame(data=data, index=index) 

Control: este código produce el resultado esperado (un diagtwig amplio):

 fig = plt.figure(figsize=(10,4)) df['A'].plot() plt.savefig("plot1.png") plt.show() 

Resultado:

plot1.png

Trazando dos líneas – el tamaño de la figura no es (10,4)

 fig = plt.figure(figsize=(10,4)) df[['A', 'B']].plot() plt.savefig("plot2.png") plt.show() 

Resultado:

plot2.png

¿Cuál es la forma correcta de hacer esto para que el tamaño de la figura se establezca de manera consistente independientemente del número de series seleccionadas?

La razón de la diferencia entre los dos casos es un poco oculta dentro de la lógica de pandas.DataFrame.plot() . Como se puede ver en la documentación, este método permite que se pasen muchos argumentos, de manera que manejará todo tipo de casos diferentes.

Aquí, en el primer caso, crea una figura de matplotlib a través de fig = plt.figure(figsize=(10,4)) y luego traza un único DataFrame de columna. Ahora, la lógica interna de la función de trazado de pandas es verificar si ya hay una figura presente en la máquina de estado matplotlib, y si es así, use los ejes actuales para trazar los valores de las columnas. Esto funciona como se esperaba.

Sin embargo, en el segundo caso, los datos constan de dos columnas. Hay varias opciones sobre cómo manejar una ttwig de este tipo, incluyendo el uso de diferentes subplots con ejes compartidos o no compartidos, etc. Para que los pandas puedan aplicar cualquiera de esos posibles requisitos, creará de forma predeterminada una nueva figura a la que Puede agregar los ejes para trazar. La nueva figura no conocerá la figura ya existente y su tamaño, sino que tendrá el tamaño predeterminado, a menos que especifique el argumento de figsize .

En los comentarios, usted dice que una posible solución es utilizar df[['A', 'B']].plot(figsize=(10,4)) . Esto es correcto, pero luego debe omitir la creación de su figura inicial. De lo contrario, producirá 2 figuras, lo que probablemente no sea deseado. En un cuaderno, esto no será visible, pero si lo ejecuta como un script de Python habitual con plt.show() al final, se plt.show() dos ventanas de figuras.

Así que la solución que permite a los pandas hacerse cargo de la creación de figuras es

 import pandas as pd import matplotlib.pyplot as plt df = pd.DataFrame({"A":[2,3,1], "B":[1,2,2]}) df[['A', 'B']].plot(figsize=(10,4)) plt.show() 

Una forma de evitar la creación de una nueva figura es suministrar el argumento ax a la función pandas.DataFrame.plot(ax=ax) , donde ax es un eje creado externamente. Estos ejes pueden ser los ejes estándar que obtiene a través de plt.gca() .

 import pandas as pd import matplotlib.pyplot as plt df = pd.DataFrame({"A":[2,3,1], "B":[1,2,2]}) plt.figure(figsize=(10,4)) df[['A', 'B']].plot(ax = plt.gca()) plt.show() 

Alternativamente, use la forma más orientada a objetos que se ve en la respuesta de PaulH .

Siempre opere explícitamente y directamente en sus objetos de Figure y Axes . No confíe en la máquina de estado de la pyplot . En tu caso eso significa:

 fig1, ax1 = plt.subplots(figsize=(10,4)) df['A'].plot(ax=ax1) fig1.savefig("plot1.png") fig2, ax2 = plt.figure(figsize=(10,4)) df[['A', 'B']].plot(ax=ax2) fig2.savefig("plot2.png") plt.show()