Search code examples
pythonpandasdatetimematplotlibxticks

How do I plot hours and minutes when they are in different pandas columns?


I have a pandas' dataframe like:

 hour   minute     cnt
    0        0  904890
    0       30  880374
    1        0  848198
    1       30  816488
    2        0  791761

I would like to plot cnt using minute as minor ticks, and hour as major tick in matplotlib. I've tried several things but they didn't work. Here's one:

fig, ax = plt.subplots(figsize=(8,5))
df.plot(kind='line', y='cnt', ax=ax)
ax.set_xticks(df['minute'])
ax.set_xticklabels(df['minute'])

I'd like my x-axis to look like

|---+---+---+---+---+---+---+---|
0   15  30  45  0   30  45  0   15
0               1           2   ...

Thanks.


Solution

  • I get this result:

    enter image description here

    with this code:

    # import
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.dates as md
    from mpl_toolkits.axes_grid1 import host_subplot
    import mpl_toolkits.axisartist as AA
    
    
    # read data and generate time column
    df = pd.read_csv('data.csv')
    df['time'] = (df['hour'].astype(str) + ':' + df['minute'].astype(str)).apply(lambda x: pd.to_datetime(str(x), format = '%H:%M'))
    
    
    # prepare figure object and axes
    fig = plt.figure(figsize = (8, 6))
    minutes = host_subplot(111, axes_class = AA.Axes, figure = fig)
    plt.subplots_adjust(bottom = 0.1)
    hours = minutes.twiny()
    
    
    # move at the bottom the secondary axis
    offset = -20
    new_fixed_axis = hours.get_grid_helper().new_fixed_axis
    hours.axis['bottom'] = new_fixed_axis(loc = 'bottom',
                                          axes = hours,
                                          offset = (0, offset))
    hours.axis['bottom'].toggle(all = True)
    
    
    # plot
    minutes.plot(df['time'], df['cnt'])
    
    
    # adjust minutes axis format, ticks and labels
    minutes.xaxis.set_major_locator(md.MinuteLocator(byminute = range(0, 60, 15)))
    minutes.xaxis.set_major_formatter(md.DateFormatter('%M'))
    plt.setp(minutes.xaxis.get_majorticklabels(), rotation = 0)
    minutes.set_xlim([df['time'].iloc[0], df['time'].iloc[-1]])
    
    
    # adjust hours axis format, ticks and labels
    hours.xaxis.set_major_locator(md.HourLocator(interval = 1))
    hours.xaxis.set_major_formatter(md.DateFormatter('%H'))
    hours.set_xlim([df['time'].iloc[0], df['time'].iloc[-1]])
    
    
    # show the plot
    plt.show()
    

    First of all, I generate a datetime column ('time'), in order to combine 'hour' and 'minute' columns. Then I prepare a figure with two axes: the primary for the minutes and the secondary for the hours. Then I proceed to manipulate the secondary axis (moving it to the bottom). Then I plot your data on the primary axis ('minutes') and finally I adjust both primary and secondary axis format, ticks, limits and labels (eventually labels rotation).