Q&A library Python

How do I work with durations in pandas?

Python Intermediate datetimedurationtimedelta

Short answer

Subtracting datetimes gives a Timedelta, which you convert to a number with total_seconds or dt.days. Use total_seconds and divide, because dt.days truncates and dt.hours only gives the hour component.

The short version

Subtracting two datetimes gives a Timedelta. Convert it to a number with dt.total_seconds() and divide to your chosen unit. Do not reach for dt.days and dt.components.hours expecting a total, because they give parts of the duration, not the whole of it.

The component trap

import pandas as pd

td = pd.Series(pd.to_timedelta(["1 days 02:00:00"]))

td.dt.days.tolist()                          # [1]  , just the days part
(td.dt.total_seconds() / 3600).tolist()      # [26.0] , the TOTAL in hours

The duration is 26 hours. dt.days reports 1, because it gives only the whole-days component, discarding the extra 2 hours. total_seconds() gives the entire duration, which you then divide into whatever unit you want.

This trips people up constantly. If you want "how many hours in total", you must use total_seconds() / 3600, not a component accessor.

Converting to common units

td.dt.total_seconds()             # seconds
td.dt.total_seconds() / 60        # minutes
td.dt.total_seconds() / 3600      # hours
td.dt.total_seconds() / 86400     # days, including the fractional part

Note the last one differs from dt.days, which truncates. A duration of 1.5 days gives 1.5 here and 1 from dt.days.

Creating a duration

pd.Timedelta(hours=2, minutes=30)
pd.Timedelta("90 minutes")

Use these for thresholds and for date arithmetic, rather than computing seconds by hand.

df[df["gap"] > pd.Timedelta(hours=24)]     # gaps of more than a day
df["deadline"] = df["created"] + pd.Timedelta(days=7)

Timedeltas aggregate

A Timedelta column supports mean, sum, min and max directly, which is convenient for summarising durations.

df["duration"].mean()      # a Timedelta, printed readably

Keep it as a Timedelta for aggregation and readability, and convert to a number only when you need to plot it, compare it against a numeric threshold, or feed it into a model.

Negative durations

Subtracting datetimes in the wrong order gives a negative Timedelta, which is valid and will quietly flow through a mean, dragging it down. If negative durations are impossible in your data, check for them, because they usually mean two timestamps are the wrong way round, which is a real data problem worth finding.

(df["end"] < df["start"]).sum()   # how many rows are inverted

The daylight saving caveat

If the two timestamps are in a local timezone and span a clock change, their difference in wall-clock terms is not the true elapsed time. Compute durations in UTC to get the real answer, which is the safe discipline for any duration that matters.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project