извлечение дней из значения numpy.timedelta64

87

Я использую pandas / python, и у меня есть два временных ряда s1 и s2, которые были сгенерированы с использованием функции to_datetime в поле df, содержащем даты / время.

Когда я вычитаю s1 из s2

s3 = s2 - s1

Я получаю серию s3 типа

timedelta64 [нс]

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

Как мне посмотреть на 1 элемент серии:

s3 [10]

Получаю примерно так:

numpy.timedelta64 (2069211000000000, 'нс')

Как мне извлечь дни из s3 и, возможно, сохранить их как целые числа (не так интересны часы / минуты и т. Д.)?

Заранее благодарю за любую помощь.

user7289
источник
4
просто к вашему сведению, собираюсь объединиться с пандами, освоите эту функцию: github.com/pydata/pandas/pull/4534 (вы можете сделать это 0.12 и ранее:s.apply(lambda x: x / np.timedelta64(1,'D'))
Джефф,

Ответы:

146

Вы можете преобразовать его в timedelta с точностью до дня. Чтобы извлечь целое число дней, вы разделите его на timedelta, равный одному дню.

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

Или, как это было предложено @PhillipCloud, просто days.astype(int)так как timedeltaэто просто 64bit целое число , которое интерпретируется по - разному в зависимости от второго параметра, переданному в ( 'D', 'ns', ...).

Вы можете узнать об этом подробнее здесь .

Виктор Керкез
источник
16
Вы также можете сделать days.item().daysили days.astype(int).
Филлип Клауд,
1
более поздние версии pandas поддерживают полноценный тип Timedelta, см. документацию здесь: pandas.pydata.org/pandas-docs/stable/timedeltas.html
Джефф,
Это хороший кандидат на .apply. Вы можете сделать это в той же строке, где вы вычисляете значения столбцов, поместив .apply (lambda x: x / np.timedelta64 (1, 'D')) в конце, чтобы применить преобразование на уровне столбца. например, s3 = (s1-s2) .apply (лямбда x: x / np.timedelta64 (1, 'D')).
Иезекииль Круглик
2
Этот метод astype('timedelta64[D]')(около 96 мс) намного более эффективен, чем dt.days.(около 24 с) для 4 000 000 строк.
Pengju Zhao
37

Используйте dt.daysдля получения атрибута days в виде целых чисел.

Например:

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

В более общем плане - вы можете использовать .componentsсвойство для доступа к сокращенной форме 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

Теперь, чтобы получить hoursатрибут:

In [23]: s.dt.components.hours
Out[23]: 
0     0
1     2
2     4
3     6
4     8
5    10
Name: hours, dtype: int64
Никил Мавели
источник
+1 - Это лучший способ сделать это на данный момент, поскольку пакет pandas прогрессировал с момента, когда был задан этот вопрос.
Austin A,
7

Предположим, у вас есть ряд 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'])

Один из способов преобразовать этот столбец или ряд timedelta - преобразовать его в объект Timedelta (pandas 0.15.0+), а затем извлечь дни из объекта:

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

Другой способ - преобразовать серию как timedelta64 в днях, а затем преобразовать ее как int:

td_series.astype('timedelta64[D]').astype(int)
Мольдвассер
источник