iayork
iayork

Reputation: 6709

pandas plot with timestamps on x axis - tick units?

I have a pandas data frame with datetime values:

    Date/Time           Event Value
0   2018-11-15 17:17:49 62
1   2018-11-15 17:27:50 63
2   2018-11-15 17:37:50 64
3   2018-11-15 17:42:49 65
4   2018-11-15 18:17:49 64
5   2018-11-15 19:27:48 65
6   2018-11-15 19:37:48 66
7   2018-11-15 19:47:49 67
8   2018-11-15 19:57:49 68
9   2018-11-15 20:12:49 69

print (tmp.dtypes)

Date/Time      datetime64[ns]
Event Value             int64

Charting it looks like this:

fig, ax1 = plt.subplots(1,1,figsize=(8,4))
tmp.plot(x='Date/Time',y='Event Value', legend=None, ax=ax1)

enter image description here

The x-axis has been formatted with appropriate dates and times (and can be further formatted using set_major_formatter).

Now I want to draw a rectangle on the chart, to highlight a particular time. To do that I need to know the x-positions.

print([x for x in ax1.get_xticks()])

[737013.7291666666, 737013.75, 737013.7708333334, 737013.7916666666, 737013.8125, 737013.8333333334]

These are indeed the x-values, i.e. if I use them as origins for the rectangle it plots as expected.

rect = patches.Rectangle((737013.75,55),.01,100)
ax1.add_patch(rect)

enter image description here

I don't understand where these numbers come from. They're not epoch values, though they look a little bit like them ('737013.75' corresponds to '1970-01-09 07:43:33', which doesn't mean anything to me).

How can I get the x-position on the chart from a Date/Time value in my dataframe?

Upvotes: 0

Views: 5899

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339480

If you plot a dataframe with the x_compat=True option you can be certain that the units are matplotlib.dates units. Else, pandas may decide some units for you.

Here, pandas uses matplotlib dates units. They are defined as:

Matplotlib represents dates using floating point numbers specifying the number of days since 0001-01-01 UTC, plus 1. For example, 0001-01-01, 06:00 is 1.25, not 0.25. Values < 1, i.e. dates before 0001-01-01 UTC are not supported.

You are however not expected to calculate those units yourself. Matplotlib provides helper functions

  • matplotlib.dates.date2num
  • matplotlib.dates.num2date
  • matplotlib.dates.datestr2num

which you can use to calculate back and forth between the units.

As an example, matplotlib.dates.datestr2num("2018-11-15 19:27:48") gives you 737013.8109722222.

Upvotes: 0

Related Questions