Plot xtick label with half hour frequency

Question:

I want the X label is like:

00:00    00:30    01:00    01:30    02:00 ...... 23:30

My code:

import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.dates as mdates
import random

data = [random.random() for i in range(48)]
times = pd.date_range('16-09-2017', periods=48, freq='30MIN')

fig, ax = plt.subplots(1)
fig.autofmt_xdate()
plt.plot(times, data)

xfmt = mdates.DateFormatter('%H:%M')
ax.xaxis.set_major_formatter(xfmt)

plt.show()

But my X-Label looks like this:

x-axis image

Whats the problem?
I have 48 values, each value represents a value for a half hour of a day

Asked By: J. Molsa

||

Answers:

Edit:
As my answer was already accepted but didn’t work correctly, I added simplified solutions for matplotlib and pandas

The key is to set x-ticks parameter correctly

In your case it could look like this:

data = [random.random() for i in range(48)]
times = pd.date_range('16-09-2017', periods=48, freq='30MIN')

In both cases, you want to use only hours and minutes:

hour_minutes = times.strftime('%H:%M')

1. Matplotlib solution

plt.figure(figsize=(12,5))
plt.plot(range(len(data)),data)
# .plot(times, data)
plt.xticks(range(len(hour_minutes)), hour_minutes, size='small',
           rotation=45, horizontalalignment='center')

plt.show()

enter image description here

2. Pandas solution

# create dataframe from arrays (not neccessary, but nice)
df = pd.DataFrame({'values': data,
                      'hour_minutes': hour_minutes})

# specify size of plot
value_plot = df.plot(figsize=(12,5), title='Value by Half-hours')
# first set number of ticks
value_plot.set_xticks(df.index)
# and label them after
value_plot.set_xticklabels(df.hour_minutes, rotation=45, size='small')

# get the plot figure and save it
fig = value_plot.get_figure()
fig.savefig('value_plot.png')

enter image description here

But I also like the alternative method that is proposed here 🙂

Answered By: StefanK

You can use the MinuteLocator and explicitly set it for every 0 and 30 minutes.

minlocator = mdates.MinuteLocator(byminute=[0,30]) 
ax.xaxis.set_major_locator(minlocator)

And to clean it up – remove extraneous tick marks and fill out the empty space.

xticks = ax.get_xticks()
ax.set_xticks(xticks[2:-2]);
hh = pd.Timedelta('30min')
ax.set_xlim(times[0] - hh, times[-1] + hh)

enter image description here

Answered By: Ted Petrou
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.