web-dev-qa-db-fra.com

Pandas: Bar-Plot avec deux barres et deux axes y

J'ai un DataFrame ressemblant à ceci:

     amount     price
age
A     40929   4066443
B     93904   9611272
C    188349  19360005
D    248438  24335536
E    205622  18888604
F    140173  12580900
G     76243   6751731
H     36859   3418329
I     29304   2758928
J     39768   3201269
K     30350   2867059

Maintenant, je voudrais tracer un graphique à barres avec l'âge sur l'axe des x comme étiquettes. Pour chaque x-tick, il devrait y avoir deux barres, une barre pour le montant et une pour le prix. Je peux faire fonctionner cela en utilisant simplement:

df.plot(kind='bar')

Le problème est la mise à l'échelle. Les prix sont tellement plus élevés que je ne peux pas vraiment identifier le montant dans ce graphique, voir:

enter image description here

Je voudrais donc un deuxième axe y. Je l'ai essayé en utilisant:

df.loc[:,'amount'].plot(kind='bar')
df.loc[:,'price'].plot(kind='bar',secondary_y=True)

mais cela écrase simplement les barres et ne les place PAS côte à côte. Y a-t-il un moyen de le faire sans avoir à accéder au matplotlib de niveau inférieur (ce qui serait évidemment possible en plaçant les barres côte à côte manuellement)?

Pour l'instant, j'utilise deux parcelles simples dans les sous-parcelles:

df.plot(kind='bar',grid=True,subplots=True,sharex=True); 

résultant en:

enter image description here

26
tim

En utilisant la nouvelle version pandas (0.14.0 ou ultérieure), le code ci-dessous fonctionnera. Pour créer les deux axes, j'ai créé manuellement deux objets axes matplotlib (ax et ax2) qui servira pour les deux graphiques à barres.

Lors du traçage d'un Dataframe, vous pouvez choisir l'objet axes à l'aide de ax=.... Aussi, pour éviter que les deux tracés ne se chevauchent, j'ai modifié leur alignement avec l'argument du mot clé position, par défaut, 0.5 mais cela signifierait que les deux graphiques à barres se chevauchent.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from io import StringIO

s = StringIO("""     amount     price
A     40929   4066443
B     93904   9611272
C    188349  19360005
D    248438  24335536
E    205622  18888604
F    140173  12580900
G     76243   6751731
H     36859   3418329
I     29304   2758928
J     39768   3201269
K     30350   2867059""")

df = pd.read_csv(s, index_col=0, delimiter=' ', skipinitialspace=True)

fig = plt.figure() # Create matplotlib figure

ax = fig.add_subplot(111) # Create matplotlib axes
ax2 = ax.twinx() # Create another axes that shares the same x-axis as ax.

width = 0.4

df.amount.plot(kind='bar', color='red', ax=ax, width=width, position=1)
df.price.plot(kind='bar', color='blue', ax=ax2, width=width, position=0)

ax.set_ylabel('Amount')
ax2.set_ylabel('Price')

plt.show()

Plot

58
Ffisegydd

Il suffit d'écrire: df.plot (kind = 'bar' , secondary_y = 'amount' )

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from io import StringIO
s = StringIO("""     amount     price
A     40929   4066443
B     93904   9611272
C    188349  19360005
D    248438  24335536
E    205622  18888604
F    140173  12580900
G     76243   6751731
H     36859   3418329
I     29304   2758928
J     39768   3201269
K     30350   2867059""")
df = pd.read_csv(s, index_col=0, delimiter=' ', skipinitialspace=True)

_ = df.plot( kind= 'bar' , secondary_y= 'amount' , rot= 0 )
plt.show()

Secondary_Y_axis

34
InLaw

Voici une autre méthode:

  • créer toutes les barres dans les axes gauches
  • déplacer certaines barres vers les axes de droite en changeant son attribut transform

Voici le code:

import pylab as pl
df = pd.DataFrame(np.random.Rand(10, 2), columns=["left", "right"])
df["left"] *= 100

ax = df.plot(kind="bar")
ax2 = ax.twinx()
for r in ax.patches[len(df):]:
    r.set_transform(ax2.transData)
ax2.set_ylim(0, 2);

voici la sortie:

enter image description here

7
HYRY