29

I am trying to plot a chart with the 1st and 2nd columns of data as bars and then a line overlay for the 3rd column of data.

I have tried the following code but this creates 2 separate charts but I would like this all on one chart.

left_2013 = pd.DataFrame({'month': ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
                     '2013_val': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 6]})

right_2014 = pd.DataFrame({'month': ['jan', 'feb'], '2014_val': [4, 5]})

right_2014_target = pd.DataFrame({'month': ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
                                   '2014_target_val': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]})


df_13_14 = pd.merge(left_2013, right_2014, how='outer')
df_13_14_target = pd.merge(df_13_14, right_2014_target, how='outer')
df_13_14_target[['month','2013_val','2014_val','2014_target_val']].head(12)

plt.figure()
df_13_14_target[['month','2014_target_val']].plot(x='month',linestyle='-', marker='o')
df_13_14_target[['month','2013_val','2014_val']].plot(x='month', kind='bar')

This is what I currently get

kpi dashboard

unutbu
  • 777,569
  • 165
  • 1,697
  • 1,613
tfayyaz
  • 595
  • 1
  • 6
  • 15
  • 1
    I managed to get this working with the following code fig, ax = plt.subplots() df_13_14_target[['month','2014_target_val']].plot(x='month',ax=ax, linestyle='--', marker='o', color='r') df_13_14_target[['month','2013_val','2014_val']].plot(x='month',ax=ax, kind='bar') However any ideas on how to make the line plots centerd above the bars – tfayyaz May 05 '14 at 21:45

1 Answers1

46

The DataFrame plotting methods return a matplotlib AxesSubplot or list of AxesSubplots. (See the docs for plot, or boxplot, for instance.)

You can then pass that same Axes to the next plotting method (using ax=ax) to draw on the same axes:

ax = df_13_14_target[['month','2014_target_val']].plot(x='month',linestyle='-', marker='o')
df_13_14_target[['month','2013_val','2014_val']].plot(x='month', kind='bar', 
   ax=ax)

import pandas as pd
import matplotlib.pyplot as plt

left_2013 = pd.DataFrame(
    {'month': ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep',
               'oct', 'nov', 'dec'],
     '2013_val': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 6]})

right_2014 = pd.DataFrame({'month': ['jan', 'feb'], '2014_val': [4, 5]})

right_2014_target = pd.DataFrame(
    {'month': ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep',
               'oct', 'nov', 'dec'],
     '2014_target_val': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]})

df_13_14 = pd.merge(left_2013, right_2014, how='outer')
df_13_14_target = pd.merge(df_13_14, right_2014_target, how='outer')

ax = df_13_14_target[['month', '2014_target_val']].plot(
    x='month', linestyle='-', marker='o')
df_13_14_target[['month', '2013_val', '2014_val']].plot(x='month', kind='bar',
                                                        ax=ax)

plt.show()

enter image description here

unutbu
  • 777,569
  • 165
  • 1,697
  • 1,613
  • 11
    The issue is with the index. By default the plot method sets ```use_index=True``` to define x axis tick labels. Try setting ```use_index=False``` and you will get the expected results. [API here](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html) –  Mar 29 '16 at 18:36
  • is there a way we can set a different axis for the line ? Say it has normalised values, I'd want to show another y axis to the right, with limits (0, 1) and have the line follow that axis – Ciprian Tomoiagă May 07 '17 at 02:51
  • `use_index=False` can be dangerous if your index values aren't identical between series... – Chris Withers Dec 28 '20 at 11:01
  • This is cool, though it doesn't work if the index is a DateTime, say if you add `df_13_14_target['month'] = pd.to_datetime(df_13_14_target['month'], format='%b')` before plotting. – rinat.io Feb 09 '22 at 20:15