63

I'd like to make a generic value -vs- time plot with python's matplotlib module. My times are in unix time but I'd like them to show up in a readable format on the plot's x-axis.

I have read answers about plotting with datetime objects but this method seems to remove hour/min/sec information and rails timestamps to the full day. Is there a way to generate these plots and show more granular labels?

1
  • Matplotlib certainly doesn't remove the time information when plotting datetimes... What exactly are you doing? Do you just want to change the labeling of the axis? Are you just wanting one tick/label per plotted data point? Commented Nov 3, 2010 at 20:01

2 Answers 2

99

It is possible to call plt.plot(dates,values) with dates being a list of datetime.datetime objects. The plot will include xticks in a format like '%Y-%m-%d' and as you zoom in, automatically change to one that shows hours, minutes, seconds.

However, it sounds like you desire more control than this. Perhaps it is not showing the hours, minutes, seconds at the scale you wish.

In that case, you can set up your own date formatter:

ax=plt.gca()
xfmt = md.DateFormatter('%Y-%m-%d %H:%M:%S')
ax.xaxis.set_major_formatter(xfmt)

Unfortunately, if you pass datetime.datetime objects to plt.plot, the xticks automatically chosen by matplotlib seems to always have seconds equal to zero. For example, if you run

import matplotlib.pyplot as plt
import matplotlib.dates as md
import numpy as np
import datetime as dt
import time

n=20
duration=1000
now=time.mktime(time.localtime())
timestamps=np.linspace(now,now+duration,n)
dates=[dt.datetime.fromtimestamp(ts) for ts in timestamps]
values=np.sin((timestamps-now)/duration*2*np.pi)
plt.subplots_adjust(bottom=0.2)
plt.xticks( rotation=25 )
ax=plt.gca()
xfmt = md.DateFormatter('%Y-%m-%d %H:%M:%S')
ax.xaxis.set_major_formatter(xfmt)
plt.plot(dates,values)
plt.show()

alt text

then you get nicely formatted dates, but all the xtick seconds are zero.

So what's the solution?

If you convert your timestamps --> datetime.datetime objects --> matplotlib datenums yourself, and pass the datenums to plt.plot, then the seconds are preserved.

PS. By "matplotlib datenum" I mean the kind of number returned by matplotlib.dates.date2num.

import matplotlib.pyplot as plt
import matplotlib.dates as md
import numpy as np
import datetime as dt
import time

n=20
duration=1000
now=time.mktime(time.localtime())
timestamps=np.linspace(now,now+duration,n)
dates=[dt.datetime.fromtimestamp(ts) for ts in timestamps]
datenums=md.date2num(dates)
values=np.sin((timestamps-now)/duration*2*np.pi)
plt.subplots_adjust(bottom=0.2)
plt.xticks( rotation=25 )
ax=plt.gca()
xfmt = md.DateFormatter('%Y-%m-%d %H:%M:%S')
ax.xaxis.set_major_formatter(xfmt)
plt.plot(datenums,values)
plt.show()

alt text

Sign up to request clarification or add additional context in comments.

3 Comments

Nice example! For what it's worth it's not that the seconds are being lost by the conversion by date2num. It's that the tick locator is automatically choosing even second locations for the tick labels.
@Joe: Yes, you are absolutely right. I started to realize that as I fumbled around editing this thing.... :)
Do the dates need to be in string format or in numeric format?
0

From here:https://matplotlib.org/stable/api/dates_api.html#matplotlib.dates.DateFormatter

import datetime
import matplotlib.dates as mdates

base = datetime.datetime(2005, 2, 1)
dates = np.array([base + datetime.timedelta(hours=(2 * i))
                  for i in range(732)])
N = len(dates)
np.random.seed(19680801)
y = np.cumsum(np.random.randn(N))

fig, ax = plt.subplots(constrained_layout=True)
locator = mdates.AutoDateLocator()
formatter = mdates.ConciseDateFormatter(locator)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)

ax.plot(dates, y)
ax.set_title('Concise Date Formatter')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.