0

I would like to plot a pandas series with timedeltas as an index and customize the x-tick format. A minimal example would be:

import pandas as pd
import matplotlib.pyplot as plt
times = ['Wed Feb 20 08:28:04 PST 2019', 'Wed Feb 20 09:29:04 PST 2019', 'Wed Feb 20 10:30:04 PST 2019']
timestamps = [pd.Timestamp(t) for t in times]
timedeltas = [t - timestamps[0] for t in timestamps]
timedeltas
ts = pd.Series([1, 2, 5], index=timedeltas)
ts.plot()
plt.savefig("/tmp/plot.png")`

Which produces the following
[output][1].

I would like to format the timedeltas as [hours]:[minutes].

Adding

import matplotlib.dates as mdates
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))

results in the following error:

ValueError: Cannot convert -1000000000000 to a date.  This often happens if non-datetime values are passed to an axis that expects datetime objects.
trotta
  • 1,232
  • 1
  • 16
  • 23
spurdo
  • 3
  • 1
  • `matplotlib.dates` strictly expects the units to be days. pandas plot may use completely different units. Hence the matplotlib formatters and locators do *in general* not work with pandas plots. You can use `x_compat=True` in many cases, but not for timedeltas. If you need to use a matplotlib formatter, convert your timedifferences to days first. – ImportanceOfBeingErnest Feb 21 '19 at 17:37

1 Answers1

0

The problem here is that we're unable to format timedeltas.

There is a great solution to this by @Shawn Chin here

I've edited his answer slighter in order to add leading zero's to the hours and minutes where applicable, solely because I think it looks nicer. Though it will limit days to 2 digits too, but from your question I'm assuming you only want to display hours and minutes.

Shawn's slightly edited function:

def strfdelta(tdelta, fmt):
    d = {"days": tdelta.days}
    d["hours"], rem = divmod(tdelta.seconds, 3600)
    d["minutes"], d["seconds"] = divmod(rem, 60)
    for key in d:
        d[key] = "{:02d}".format(d[key])
    return fmt.format(**d)

Adding one extra line in your code to call this function I hope yields the output you're after:

import pandas as pd
import matplotlib.pyplot as plt
times = ['Wed Feb 20 08:28:04 PST 2019', 'Wed Feb 20 09:29:04 PST 2019', 'Wed Feb 20 10:30:04 PST 2019']
timestamps = [pd.Timestamp(t) for t in times]
timedeltas = [t - timestamps[0] for t in timestamps]
timedeltas = [strfdelta(t, '{hours}:{minutes}') for t in timedeltas]
ts = pd.Series([1, 2, 5], index=timedeltas)
ts.plot()

Line Chart Output

Hope this helps!

JimmyA
  • 676
  • 5
  • 13
  • Thank you very much for your answer. However there are no labels on the x-axis for me. I'm using Python 3.6.7 with pandas 0.22.0 and matplotlib 3.0.0 in case this matters. – spurdo Feb 21 '19 at 18:15
  • @spurdo Sorry to hear it. Can you show me what ts looks like for you? – JimmyA Feb 21 '19 at 18:59
  • @RockHardRaccon [This is what it looks like for me](https://i.imgur.com/K01moPe.png) – spurdo Feb 22 '19 at 11:02
  • @spurdo Do the values appear in your pandas series, the ts variable? – JimmyA Feb 22 '19 at 11:06