Extrahieren von Tagen aus einem numpy.timedelta64-Wert

87

Ich verwende pandas / python und habe zwei Datumszeitreihen s1 und s2, die mit der Funktion 'to_datetime' in einem Feld des df generiert wurden, das Datums- / Uhrzeitangaben enthält.

Wenn ich s1 von s2 subtrahiere

s3 = s2 - s1

Ich bekomme eine Serie, s3, vom Typ

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

Wie sehe ich 1 Element der Serie:

s3 [10]

Ich bekomme so etwas:

numpy.timedelta64 (2069211000000000, 'ns')

Wie extrahiere ich Tage aus s3 und behalte sie vielleicht als ganze Zahlen (nicht so interessiert an Stunden / Minuten usw.)?

Vielen Dank im Voraus für jede Hilfe.

user7289
quelle
4
Nur zu Ihrer Information, kurz vor dem Zusammenschluss mit Pandas. Meistern Sie diese Funktion: github.com/pydata/pandas/pull/4534 (Sie können dies ab 0.12 tun:s.apply(lambda x: x / np.timedelta64(1,'D'))
Jeff

Antworten:

146

Sie können es mit einer Tagesgenauigkeit in ein Zeitdelta konvertieren. Um den ganzzahligen Wert von Tagen zu extrahieren, teilen Sie ihn durch ein Zeitdelta von einem Tag.

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

Oder, wie @PhillipCloud vorgeschlagen, nur days.astype(int)weil das timedeltaist nur eine 64 - Bit - Ganzzahl, die Sie übergaben auf verschiedene Weise in Abhängigkeit von dem zweiten Parameter interpretiert wird ( 'D', 'ns', ...).

Mehr dazu finden Sie hier .

Viktor Kerkez
quelle
16
Sie können auch tun days.item().daysoder days.astype(int).
Phillip Cloud
1
Neuere Versionen von Pandas unterstützen einen vollwertigen Timedelta-Typ. Weitere Informationen finden Sie hier: pandas.pydata.org/pandas-docs/stable/timedeltas.html
Jeff,
Dies ist ein guter Kandidat für .apply. Sie können dies in derselben Zeile tun, in der Sie Spaltenwerte berechnen, indem Sie am Ende .apply (Lambda x: x / np.timedelta64 (1, 'D')) einfügen, um die Konvertierung auf Spaltenebene anzuwenden. zB s3 = (s1-s2) .apply (Lambda x: x / np.timedelta64 (1, 'D')).
Ezekiel Kruglick
2
Diese Methode astype('timedelta64[D]')(ca. 96 ms) ist dt.days.für 4.000.000 Zeilen viel effizienter als (ca. 24 s) .
Pengju Zhao
38

Verwenden Sie dt.daysdiese Option , um das Attribut days als Ganzzahlen abzurufen.

Zum Beispiel:

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

Allgemeiner - Sie können die .componentsEigenschaft verwenden, um auf eine reduzierte Form von zuzugreifen 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

Um das hoursAttribut zu erhalten:

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
quelle
+1 - Dies ist derzeit der beste Weg, dies zu tun, da das Pandas-Paket seit dem Stellen dieser Frage Fortschritte gemacht hat.
Austin A
7

Angenommen, Sie haben eine Timedelta-Reihe:

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'])

Eine Möglichkeit, diese Timedelta-Spalte oder -Serie zu konvertieren, besteht darin, sie in ein Timedelta-Objekt (Pandas 0.15.0+) umzuwandeln und dann die Tage aus dem Objekt zu extrahieren:

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

Eine andere Möglichkeit besteht darin, die Serie in Tagen als timedelta64 und dann als int:

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