Pandas: Bar-Plot with two bars and two y-axis
Using the new pandas release (0.14.0 or later) the below code will work. To create the two axis I have manually created two matplotlib axes objects (ax
and ax2
) which will serve for both bar plots.
When plotting a Dataframe you can choose the axes object using ax=...
. Also in order to prevent the two plots from overlapping I have modified where they align with the position
keyword argument, this defaults to 0.5
but that would mean the two bar plots overlapping.
import matplotlib.pyplot as pltimport numpy as npimport pandas as pdfrom io import StringIOs = StringIO(""" amount priceA 40929 4066443B 93904 9611272C 188349 19360005D 248438 24335536E 205622 18888604F 140173 12580900G 76243 6751731H 36859 3418329I 29304 2758928J 39768 3201269K 30350 2867059""")df = pd.read_csv(s, index_col=0, delimiter=' ', skipinitialspace=True)fig = plt.figure() # Create matplotlib figureax = fig.add_subplot(111) # Create matplotlib axesax2 = ax.twinx() # Create another axes that shares the same x-axis as ax.width = 0.4df.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()
You just need to write: df.plot( kind= 'bar', secondary_y= 'amount')
import matplotlib.pyplot as pltimport numpy as npimport pandas as pdfrom io import StringIOs = StringIO(""" amount priceA 40929 4066443B 93904 9611272C 188349 19360005D 248438 24335536E 205622 18888604F 140173 12580900G 76243 6751731H 36859 3418329I 29304 2758928J 39768 3201269K 30350 2867059""")df = pd.read_csv(s, index_col=0, delimiter=' ', skipinitialspace=True)_ = df.plot( kind= 'bar' , secondary_y= 'amount' , rot= 0 )plt.show()
Here is an other method:
- create all the bars in left axes
- move some bars to the right axes by change it's
transform
attribute
Here is the code:
import pylab as pldf = pd.DataFrame(np.random.rand(10, 2), columns=["left", "right"])df["left"] *= 100ax = df.plot(kind="bar")ax2 = ax.twinx()for r in ax.patches[len(df):]: r.set_transform(ax2.transData)ax2.set_ylim(0, 2);
here is the output: