web-dev-qa-db-fra.com

Incohérence lors de la définition de la taille de la figure à l'aide de la méthode de tracé pandas

J'essaie d'utiliser la commodité de la méthode de tracé d'une trame de données pandas tout en ajustant la taille de la figure produite. (J'enregistre les figures dans un fichier et les affiche en ligne dans un cahier Jupyter.) J'ai trouvé la méthode ci-dessous réussie la plupart du temps, sauf lorsque je trace deux lignes sur le même graphique - puis la figure revient à la taille par défaut.

Je soupçonne que cela pourrait être dû aux différences entre l'intrigue sur une série et l'intrigue sur une trame de données.

Exemple de code de configuration:

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)

Contrôle - ce code produit le résultat attendu (un large tracé):

fig = plt.figure(figsize=(10,4))

df['A'].plot()
plt.savefig("plot1.png")
plt.show()

Résultat:

plot1.png

Tracer deux lignes - la taille de la figure n'est pas (10,4)

fig = plt.figure(figsize=(10,4))

df[['A', 'B']].plot()
plt.savefig("plot2.png")
plt.show()

Résultat:

plot2.png

Quelle est la bonne façon de procéder pour que la taille de la figure soit définie de manière cohérente quel que soit le nombre de séries sélectionnées?

11
Bill

La raison de la différence entre les deux cas est un peu cachée dans la logique de pandas.DataFrame.plot(). Comme on peut le voir dans la documentation cette méthode permet de passer beaucoup d'arguments de telle sorte qu'elle gère toutes sortes de cas différents.

Ici, dans le premier cas, vous créez une figure matplotlib via fig = plt.figure(figsize=(10,4)), puis tracez une seule colonne DataFrame. La logique interne de pandas plot) consiste à vérifier s'il existe déjà un chiffre dans la machine à états matplotlib, et si c'est le cas, utilisez ses axes actuels pour tracer les valeurs des colonnes. fonctionne comme prévu.

Cependant, dans le deuxième cas, les données se composent de deux colonnes. Il existe plusieurs options pour gérer un tel tracé, y compris l'utilisation de différents sous-tracés avec des axes partagés ou non partagés, etc. Pour que pandas puisse appliquer l'une de ces exigences possibles, il faudra crée par défaut une nouvelle figure à laquelle il peut ajouter les axes à tracer. La nouvelle figure ne connaîtra pas la figure déjà existante et sa taille, mais aura plutôt la taille par défaut, sauf si vous spécifiez l'argument figsize .

Dans les commentaires, vous dites qu'une solution possible est d'utiliser df[['A', 'B']].plot(figsize=(10,4)). C'est correct, mais vous devez ensuite omettre la création de votre chiffre initial. Sinon, il produira 2 chiffres, ce qui n'est probablement pas souhaité. Dans un cahier, cela ne sera pas visible, mais si vous l'exécutez comme un script python avec plt.show() à la fin, il y aura deux fenêtres de figures qui s'ouvriront.

Ainsi, la solution qui permet à pandas de s’occuper de la création de figurines est

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()

Un moyen de contourner la création d'une nouvelle figure consiste à fournir l'argument ax à la fonction pandas.DataFrame.plot(ax=ax), où ax est un axe créé en externe. Ces axes peuvent être les axes standard que vous obtenez via 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()

Vous pouvez également utiliser la manière plus orientée objet vue dans le réponse de PaulH .

20

Toujours opérer explicitement et directement sur vos objets Figure et Axes. Ne vous fiez pas à la machine d'état pyplot. Dans votre cas, cela signifie:

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()
5
Paul H