Christopher H
Christopher H

Reputation: 113

How to combine bar and line plots with x-axis as datetime in matplotlib

I have a dataFrame with datetimeIndex and two columns with int values. I would like to plot on the same graph Col1 as a bar plot, and Col2 as a line plot.

Important feature is to have correctly labeled x-axis as datetime, also when zooming in-out. I think solutions with DateFormatter would not work, since I want a dynamic xtick labeling.

import matplotlib.pyplot as plt
import pandas as pd
import datetime as dt
import numpy as np

startDate = dt.datetime(2018,1,1,0,0)
nrHours = 144
datetimeIndex = [startDate + dt.timedelta(hours=x) for x in  range(0,nrHours)]

dF = pd.DataFrame(index=datetimeIndex)
dF['Col1'] = np.random.randint(1,3,nrHours)
dF['Col2'] = np.random.randint(3,6,nrHours)

axes = dF[['Col1']].plot(kind='bar')
dF[['Col2']].plot(ax=axes)

What seemed to be a simple task turns out being very challenging. Actually, after extensive search on the net, I still haven't found any clean solutions.

I have tried to use both pandas plot and matplotlib. The main issue arises from the bar plot that seems to have difficulties handling datetime index (prefers integers, in some cases it plot dates but in Epoch 1970-1-1 style which is equivalent to 0).

Upvotes: 3

Views: 2823

Answers (1)

Christopher H
Christopher H

Reputation: 113

I finally found a way using mdates and date2num. The solution is not very clean but provides an efficient solution to:

  • Combine bar and line plot on same graph
  • Using datetime on x-axis
  • Correctly and dynamically displaying x-ticks time labels (also when zooming in and out)

Working example :

import matplotlib.pyplot as plt
import matplotlib.dates  as mdates
import pandas as pd
import datetime as dt
import numpy as np

startDate = dt.datetime(2018,1,1,0,0)
nrHours = 144
datetimeIndex = [startDate + dt.timedelta(hours=x) for x in range(0, nrHours)]

dF = pd.DataFrame(index=datetimeIndex)
dF['Col1'] = np.random.randint(1,3,nrHours)
dF['Col2'] = np.random.randint(3,6,nrHours)

fig,axes = plt.subplots()
axes.xaxis_date()
axes.plot(mdates.date2num(list(dF.index)),dF['Col2'])
axes.bar(mdates.date2num(list(dF.index)),dF['Col1'],align='center',width=0.02)
fig.autofmt_xdate()

Sample output:

enter image description here

Upvotes: 5

Related Questions