extração de dias de um valor numpy.timedelta64

87

Estou usando o pandas / python e tenho duas séries de tempo de data s1 e s2, que foram geradas usando a função 'to_datetime' em um campo do df contendo datas / horas.

Quando eu subtraio s1 de s2

s3 = s2 - s1

Eu recebo uma série, s3, do tipo

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

Como vejo 1 elemento da série:

s3 [10]

Eu recebo algo assim:

numpy.timedelta64 (2069211000000000, 'ns')

Como faço para extrair dias de s3 e talvez mantê-los como inteiros (não tão interessado em horas / minutos etc.)?

Agradecemos antecipadamente por qualquer ajuda.

user7289
fonte
4
apenas para sua informação, prestes a se fundir com os pandas, domine esta funcionalidade: github.com/pydata/pandas/pull/4534 (você pode fazer isso em 0,12 e antes de:s.apply(lambda x: x / np.timedelta64(1,'D'))
Jeff

Respostas:

146

Você pode convertê-lo em um timedelta com uma precisão de dia. Para extrair o valor inteiro dos dias, você o divide por um intervalo de tempo de um dia.

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

Ou, como @PhillipCloud sugeriu, apenas days.astype(int)desde que o timedeltaé apenas um número inteiro de 64 bits que é interpretado de várias maneiras, dependendo do segundo parâmetro que você passou no ( 'D', 'ns'...).

Você pode encontrar mais sobre isso aqui .

Viktor Kerkez
fonte
16
Você também pode fazer days.item().daysou days.astype(int).
Phillip Cloud
1
versões mais recentes de pandas suportam um tipo completo de Timedelta, veja os documentos aqui: pandas.pydata.org/pandas-docs/stable/timedeltas.html
Jeff
Este é um bom candidato para .apply. Você pode fazer isso na mesma linha em que calcula os valores da coluna, colocando .apply (lambda x: x / np.timedelta64 (1, 'D')) no final para aplicar a conversão no nível da coluna. por exemplo, s3 = (s1-s2) .aplicar (lambda x: x / np.timedelta64 (1, 'D')).
Ezekiel Kruglick
2
Este método astype('timedelta64[D]')(cerca de 96 ms) é muito mais eficiente do que dt.days.(cerca de 24 s) para 4.000.000 de linhas.
Pengju Zhao
37

Use dt.dayspara obter o atributo dias como inteiros.

Por exemplo:

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

De forma mais geral - você pode usar a .componentspropriedade para acessar um formulário reduzido 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

Agora, para obter o hoursatributo:

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
fonte
+1 - Esta é a melhor maneira de fazer isso atualmente, pois o pacote pandas progrediu desde que esta pergunta foi feita.
Austin A de
7

Suponha que você tenha uma 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'])

Uma maneira de converter esta coluna ou série timedelta é lançá-la em um objeto Timedelta (pandas 0.15.0+) e extrair os dias do objeto:

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

Outra maneira é lançar a série como um timedelta64 em dias e, em seguida, lançá-la como um int:

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