.. currentmodule:: pandas
.. ipython:: python :suppress: from datetime import datetime, timedelta import numpy as np np.random.seed(123456) from pandas import * randn = np.random.randn randint = np.random.randint np.set_printoptions(precision=4, suppress=True) options.display.max_rows=15 import dateutil import pytz from dateutil.relativedelta import relativedelta from pandas.tseries.api import * from pandas.tseries.offsets import *
Note
Starting in v0.15.0, we introduce a new scalar type Timedelta
, which is a subclass of datetime.timedelta
, and behaves in a similar manner,
but allows compatibility with np.timedelta64
types as well as a host of custom representation, parsing, and attributes.
Timedeltas are differences in times, expressed in difference units, e.g. days,hours,minutes,seconds. They can be both positive and negative.
You can construct a Timedelta
scalar thru various arguments:
.. ipython:: python # strings Timedelta('1 days') Timedelta('1 days 00:00:00') Timedelta('1 days 2 hours') Timedelta('-1 days 2 min 3us') # like datetime.timedelta # note: these MUST be specified as keyword argments Timedelta(days=1,seconds=1) # integers with a unit Timedelta(1,unit='d') # from a timedelta/np.timedelta64 Timedelta(timedelta(days=1,seconds=1)) Timedelta(np.timedelta64(1,'ms')) # negative Timedeltas have this string repr # to be more consistent with datetime.timedelta conventions Timedelta('-1us') # a NaT Timedelta('nan') Timedelta('nat')
:ref:`DateOffsets<timeseries.offsets>` (Day, Hour, Minute, Second, Milli, Micro, Nano
) can also be used in construction.
.. ipython:: python Timedelta(Second(2))
Further, operations among the scalars yield another scalar Timedelta
.. ipython:: python Timedelta(Day(2)) + Timedelta(Second(2)) + Timedelta('00:00:00.000123')
Warning
Prior to 0.15.0 pd.to_timedelta
would return a Series
for list-like/Series input, and a np.timedelta64
for scalar input.
It will now return a TimedeltaIndex
for list-like input, Series
for Series input, and Timedelta
for scalar input.
The arguments to pd.to_timedelta
are now (arg,unit='ns',box=True)
, previously were (arg,box=True,unit='ns')
as these are more logical.
Using the top-level pd.to_timedelta
, you can convert a scalar, array, list, or Series from a recognized timedelta format / value into a Timedelta
type.
It will construct Series if the input is a Series, a scalar if the input is scalar-like, otherwise will output a TimedeltaIndex
.. ipython:: python to_timedelta('1 days 06:05:01.00003') to_timedelta('15.5us') to_timedelta(['1 days 06:05:01.00003','15.5us','nan']) to_timedelta(np.arange(5),unit='s') to_timedelta(np.arange(5),unit='d')
You can operate on Series/DataFrames and construct timedelta64[ns]
Series thru
subtraction operations on datetime64[ns]
Series, or Timestamps
.
.. ipython:: python s = Series(date_range('2012-1-1', periods=3, freq='D')) td = Series([ Timedelta(days=i) for i in range(3) ]) df = DataFrame(dict(A = s, B = td)) df df['C'] = df['A'] + df['B'] df df.dtypes s - s.max() s - datetime(2011,1,1,3,5) s + timedelta(minutes=5) s + Minute(5) s + Minute(5) + Milli(5)
Operations with scalars from a timedelta64[ns]
series
.. ipython:: python y = s - s[0] y
Series of timedeltas with NaT
values are supported
.. ipython:: python y = s - s.shift() y
Elements can be set to NaT
using np.nan
analogously to datetimes
.. ipython:: python y[1] = np.nan y
Operands can also appear in a reversed order (a singular object operated with a Series)
.. ipython:: python s.max() - s datetime(2011,1,1,3,5) - s timedelta(minutes=5) + s
min, max
and the corresponding idxmin, idxmax
operations are supported on frames
.. ipython:: python A = s - Timestamp('20120101') - Timedelta('00:05:05') B = s - Series(date_range('2012-1-2', periods=3, freq='D')) df = DataFrame(dict(A=A, B=B)) df df.min() df.min(axis=1) df.idxmin() df.idxmax()
min, max, idxmin, idxmax
operations are supported on Series as well. A scalar result will be a Timedelta
.
.. ipython:: python df.min().max() df.min(axis=1).min() df.min().idxmax() df.min(axis=1).idxmin()
You can fillna on timedeltas. Integers will be interpreted as seconds. You can pass a timedelta to get a particular value.
.. ipython:: python y.fillna(0) y.fillna(10) y.fillna(Timedelta('-1 days, 00:00:05'))
You can also negate, multiply and use abs
on Timedeltas
.. ipython:: python td1 = Timedelta('-1 days 2 hours 3 seconds') td1 -1 * td1 - td1 abs(td1)
Numeric reduction operation for timedelta64[ns]
will return Timedelta
objects. As usual
NaT
are skipped during evaluation.
.. ipython:: python y2 = Series(to_timedelta(['-1 days +00:00:05','nat','-1 days +00:00:05','1 days'])) y2 y2.mean() y2.median() y2.quantile(.1) y2.sum()
.. versionadded:: 0.13
Timedelta Series, TimedeltaIndex
, and Timedelta
scalars can be converted to other 'frequencies' by dividing by another timedelta,
or by astyping to a specific timedelta type. These operations yield Series and propogate NaT
-> nan
.
Note that division by the numpy scalar is true division, while astyping is equivalent of floor division.
.. ipython:: python td = Series(date_range('20130101',periods=4)) - \ Series(date_range('20121201',periods=4)) td[2] += timedelta(minutes=5,seconds=3) td[3] = np.nan td # to days td / np.timedelta64(1,'D') td.astype('timedelta64[D]') # to seconds td / np.timedelta64(1,'s') td.astype('timedelta64[s]') # to months (these are constant months) td / np.timedelta64(1,'M')
Dividing or multiplying a timedelta64[ns]
Series by an integer or integer Series
yields another timedelta64[ns]
dtypes Series.
.. ipython:: python td * -1 td * Series([1,2,3,4])
You can access various components of the Timedelta
or TimedeltaIndex
directly using the attributes days,hours,minutes,seconds,milliseconds,microseconds,nanoseconds
.
These operations can be directly accessed via the .dt
property of the Series
as well. These return an integer representing that interval (which is signed according to whether the Timedelta
is signed).
For a Series
.. ipython:: python td.dt.days td.dt.seconds
You can access the component field for a scalar Timedelta
directly.
.. ipython:: python tds = Timedelta('31 days 5 min 3 sec') tds.days tds.seconds (-tds).seconds
You can use the .components
property to access a reduced form of the timedelta. This returns a DataFrame
indexed
similarly to the Series
.. ipython:: python td.dt.components
Warning
Timedelta
scalars (and TimedeltaIndex
) component fields are not the same as the component fields on a datetime.timedelta
object. For example, .seconds
on a datetime.timedelta
object returns the total number of seconds combined between hours
, minutes
and seconds
. In contrast, the pandas Timedelta
breaks out hours, minutes, microseconds and nanoseconds separately.
.. ipython:: python # Timedelta accessor tds = Timedelta('31 days 5 min 3 sec') tds.minutes tds.seconds # datetime.timedelta accessor # this is 5 minutes * 60 + 3 seconds tds.to_pytimedelta().seconds
.. versionadded:: 0.15.0
To generate an index with time delta, you can use either the TimedeltaIndex or
the timedelta_range
constructor.
Using TimedeltaIndex
you can pass string-like, Timedelta
, timedelta
,
or np.timedelta64
objects. Passing np.nan/pd.NaT/nat
will represent missing values.
.. ipython:: python TimedeltaIndex(['1 days','1 days, 00:00:05', np.timedelta64(2,'D'),timedelta(days=2,seconds=2)])
Similarly to date_range
, you can construct regular ranges of a TimedeltaIndex
:
.. ipython:: python timedelta_range(start='1 days',periods=5,freq='D') timedelta_range(start='1 days',end='2 days',freq='30T')
Similarly to other of the datetime-like indices, DatetimeIndex
and PeriodIndex
, you can use
TimedeltaIndex
as the index of pandas objects.
.. ipython:: python s = Series(np.arange(100), index=timedelta_range('1 days',periods=100,freq='h')) s
Selections work similary, with coercion on string-likes and slices:
.. ipython:: python s['1 day':'2 day'] s['1 day 01:00:00'] s[Timedelta('1 day 1h')]
Furthermore you can use partial string selection and the range will be inferred:
.. ipython:: python s['1 day':'1 day 5 hours']
Finally, the combination of TimedeltaIndex
with DatetimeIndex
allow certain combination operations that are NaT preserving:
.. ipython:: python tdi = TimedeltaIndex(['1 days',pd.NaT,'2 days']) tdi.tolist() dti = date_range('20130101',periods=3) dti.tolist() (dti + tdi).tolist() (dti - tdi).tolist()
Similarly to frequency conversion on a Series
above, you can convert these indices to yield another Index.
.. ipython:: python tdi / np.timedelta64(1,'s') tdi.astype('timedelta64[s]')
Scalars type ops work as well. These can potentially return a different type of index.
.. ipython:: python # adding or timedelta and date -> datelike tdi + Timestamp('20130101') # subtraction of a date and a timedelta -> datelike # note that trying to subtract a date from a Timedelta will raise an exception (Timestamp('20130101') - tdi).tolist() # timedelta + timedelta -> timedelta tdi + Timedelta('10 days') # division can result in a Timedelta if the divisor is an integer tdi / 2 # or a Float64Index if the divisor is a Timedelta tdi / tdi[0]
Similar to :ref:`timeseries resampling <timeseries.resampling>`, we can resample with a TimedeltaIndex
.
.. ipython:: python s.resample('D')