extraction de jours à partir d'une valeur numpy.timedelta64

87

J'utilise pandas / python et j'ai deux séries temporelles de date s1 et s2, qui ont été générées à l'aide de la fonction 'to_datetime' sur un champ du df contenant des dates / heures.

Quand je soustrais s1 de s2

s3 = s2 - s1

Je reçois une série, s3, de type

timedelta64 [ns]

0    385 days, 04:10:36
1     57 days, 22:54:00
2    642 days, 21:15:23
3    615 days, 00:55:44
4    160 days, 22:13:35
5    196 days, 23:06:49
6     23 days, 22:57:17
7      2 days, 22:17:31
8    622 days, 01:29:25
9     79 days, 20:15:14
10    23 days, 22:46:51
11   268 days, 19:23:04
12                  NaT
13                  NaT
14   583 days, 03:40:39

Comment regarder 1 élément de la série:

s3 [10]

J'obtiens quelque chose comme ça:

numpy.timedelta64 (2069211000000000, 'ns')

Comment extraire des jours de s3 et peut-être les conserver sous forme d'entiers (pas trop intéressés par les heures / minutes, etc.)

Merci d'avance pour votre aide.

user7289
la source
4
juste pour info, sur le point de fusionner avec les pandas maîtrisez cette fonctionnalité: github.com/pydata/pandas/pull/4534 (vous pouvez le faire le 0.12 et avant par:s.apply(lambda x: x / np.timedelta64(1,'D'))
Jeff

Réponses:

146

Vous pouvez le convertir en chronomètre avec une précision d'un jour. Pour extraire la valeur entière des jours, vous la divisez par un delta temporel d'un jour.

>>> x = np.timedelta64(2069211000000000, 'ns')
>>> days = x.astype('timedelta64[D]')
>>> days / np.timedelta64(1, 'D')
23

Ou, comme @PhillipCloud suggéré, juste days.astype(int)puisque le timedeltaest juste un entier de 64 bits qui est interprété de diverses manières en fonction du deuxième paramètre que vous avez passé dans ( 'D', 'ns'...).

Vous pouvez en savoir plus ici .

Viktor Kerkez
la source
16
Vous pouvez également faire days.item().daysou days.astype(int).
Phillip Cloud
1
les versions plus récentes de pandas prennent en charge un type Timedelta à part entière, voir la documentation ici: pandas.pydata.org/pandas-docs/stable/timedeltas.html
Jeff
C'est un bon candidat pour .apply. Vous pouvez le faire dans la même ligne où vous calculez les valeurs de colonne en mettant .apply (lambda x: x / np.timedelta64 (1, 'D')) à la fin pour appliquer la conversion au niveau de la colonne. par exemple s3 = (s1-s2) .apply (lambda x: x / np.timedelta64 (1, 'D')).
Ezekiel Kruglick
2
Cette méthode astype('timedelta64[D]')(environ 96 ms) est beaucoup plus efficace que dt.days.(environ 24 s) pour 4 000 000 de lignes.
Pengju Zhao du
37

Utilisez dt.dayspour obtenir l'attribut jours sous forme d'entiers.

Par exemple:

In [14]: s = pd.Series(pd.timedelta_range(start='1 days', end='12 days', freq='3000T'))

In [15]: s
Out[15]: 
0    1 days 00:00:00
1    3 days 02:00:00
2    5 days 04:00:00
3    7 days 06:00:00
4    9 days 08:00:00
5   11 days 10:00:00
dtype: timedelta64[ns]

In [16]: s.dt.days
Out[16]: 
0     1
1     3
2     5
3     7
4     9
5    11
dtype: int64

Plus généralement - Vous pouvez utiliser la .componentspropriété pour accéder à une forme réduite de timedelta.

In [17]: s.dt.components
Out[17]: 
   days  hours  minutes  seconds  milliseconds  microseconds  nanoseconds
0     1      0        0        0             0             0            0
1     3      2        0        0             0             0            0
2     5      4        0        0             0             0            0
3     7      6        0        0             0             0            0
4     9      8        0        0             0             0            0
5    11     10        0        0             0             0            0

Maintenant, pour obtenir l' hoursattribut:

In [23]: s.dt.components.hours
Out[23]: 
0     0
1     2
2     4
3     6
4     8
5    10
Name: hours, dtype: int64
Nickil Maveli
la source
+1 - C'est la meilleure façon de le faire actuellement puisque le paquet pandas a progressé depuis que cette question a été posée.
Austin A
7

Supposons que vous ayez une série timedelta:

import pandas as pd
from datetime import datetime
z = pd.DataFrame({'a':[datetime.strptime('20150101', '%Y%m%d')],'b':[datetime.strptime('20140601', '%Y%m%d')]})

td_series = (z['a'] - z['b'])

Une façon de convertir cette colonne ou série timedelta est de la convertir en un objet Timedelta (pandas 0.15.0+), puis d'extraire les jours de l'objet:

td_series.astype(pd.Timedelta).apply(lambda l: l.days)

Une autre façon consiste à convertir la série en timedelta64 en jours, puis à la convertir en int:

td_series.astype('timedelta64[D]').astype(int)
mgoldwasser
la source