Skip to content
Advertisement

Matplotlib dates.DateFormatter forcing the display of nanoseconds

I encounter an issue with Matplotlib.dates.DateFormatter :

I want to convert timestamps in Date format which is simple usually with the straftime but when using it on matplotlib i don’t have the dynamic position on my graph so I used the md.DateFormatter('%H:%M:%S.%f') to have the X values as a date format with the dynamic index.

The fact is, my dates have too much values, I don’t want the nanoseconds but I don’t know how to remove them. I searched on StackOverflow to find a solution but applying a date[:-3] won’t work as I have a datetime format…

Do you have a solution? It’s maybe trivial but can’t find any solution right now… Thanks in advance.

NB : What I call the dynamic index is when you are on the graph and you can see the exact X and Y value of your pointer at the bottom

Here is an applicable example :

df =
               timestamp        val
0   2022-03-13 03:19:59.999070  X1
1   2022-03-13 03:20:00.004070  X2
2   2022-03-13 03:20:00.009070  X3 
3   2022-03-13 03:20:00.014070  X4

And I try to plot this with :

ax=plt.gca()
xfmt = md.DateFormatter('%H:%M:%S.%f')
ax.xaxis.set_major_formatter(xfmt)
plt.plot(df.timestamp, df.val, linestyle="-", marker = ".")

plt.setp(ax.get_xticklabels(), rotation=40)
plt.show()

In conclusin, what I want is to remove the 070 in the graph but if I remove it beforehand, DateFormatter will replace it by 000 which is as useless as it was..

Advertisement

Answer

If you want to change both the tick labels and the format of the number shown on the interactive status bar, you could define your own function to deliver your desired format, then use a FuncFormatter to display those values on your plot.

For example:

import matplotlib.pyplot as plt
import matplotlib.dates as md
import pandas as pd

# dummy data
ts = pd.date_range("2022-03-13 03:19:59.999070",
                   "2022-03-13 03:20:00.014070", periods=4)
df = pd.DataFrame({'timestamp': ts, 'val':[0, 1, 2, 3]})

fig, ax = plt.subplots()

# define our own function to drop the last three characters
xfmt = lambda x, pos: md.DateFormatter('%H:%M:%S.%f')(x)[:-3]

# use that function as the major formatter, using FuncFormatter
ax.xaxis.set_major_formatter(plt.FuncFormatter(xfmt))

plt.setp(ax.get_xticklabels(), rotation=40)

ax.plot(df.timestamp, df.val, linestyle="-", marker = ".")

plt.tight_layout()
plt.show()

enter image description here Note the matching tick format and status bar format.

If, however, you do not want to change the tick labels, but only change the value on the status bar, we can do that by reassigning the ax.format_coord function, using the a similar idea for the function we defined above, but also adding in the y value for display

For example:

import matplotlib.pyplot as plt
import matplotlib.dates as md
import pandas as pd

# dummy data
ts = pd.date_range("2022-03-13 03:19:59.999070",
                   "2022-03-13 03:20:00.014070", periods=4)
df = pd.DataFrame({'timestamp': ts, 'val':[0, 1, 2, 3]})

fig, ax = plt.subplots()

xfmt = md.DateFormatter('%H:%M:%S.%f')
xfmt2 = lambda x, y: "x={}, y={:g}".format(xfmt(x)[:-3], y)

# use original formatter here with microseconds
ax.xaxis.set_major_formatter(plt.FuncFormatter(xfmt))

# and the millisecond function here
ax.format_coord = xfmt2

plt.setp(ax.get_xticklabels(), rotation=40)

ax.plot(df.timestamp, df.val, linestyle="-", marker = ".")

plt.tight_layout()
plt.show()

enter image description here Note the difference between the status bar and the tick formats here.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement