Berechnen Sie den Zeitunterschied zwischen zwei Spalten in Stunden und Minuten für Pandas DataFrame


85

Ich habe zwei Spalten fromdateund todatein einem Datenrahmen.

import pandas as pd

data = {'todate': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000'), pd.Timestamp('2014-01-23 10:07:47.660000')],
        'fromdate': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000'), pd.Timestamp('2014-01-23 18:50:41.420000')]}

df = pd.DataFrame(data)

Ich füge eine neue Spalte hinzu, diffum den Unterschied zwischen den beiden Daten mithilfe von zu ermitteln

df['diff'] = df['fromdate'] - df['todate']

Ich bekomme die diffKolumne, aber sie enthält days, wenn es mehr als 24 Stunden gibt.

                   todate                fromdate                   diff
0 2014-01-24 13:03:12.050 2014-01-26 23:41:21.870 2 days 10:38:09.820000
1 2014-01-27 11:57:18.240 2014-01-27 15:38:22.540 0 days 03:41:04.300000
2 2014-01-23 10:07:47.660 2014-01-23 18:50:41.420 0 days 08:42:53.760000

Wie konvertiere ich meine Ergebnisse in nur Stunden und Minuten (dh Tage werden in Stunden konvertiert)?

Antworten:


123

Pandas Zeitstempeldifferenzen geben ein datetime.timedelta-Objekt zurück. Dies kann einfach mit der Methode * as_type * in Stunden umgewandelt werden

import pandas
df = pandas.DataFrame(columns=['to','fr','ans'])
df.to = [pandas.Timestamp('2014-01-24 13:03:12.050000'), pandas.Timestamp('2014-01-27 11:57:18.240000'), pandas.Timestamp('2014-01-23 10:07:47.660000')]
df.fr = [pandas.Timestamp('2014-01-26 23:41:21.870000'), pandas.Timestamp('2014-01-27 15:38:22.540000'), pandas.Timestamp('2014-01-23 18:50:41.420000')]
(df.fr-df.to).astype('timedelta64[h]')

nachgeben,

0    58
1     3
2     8
dtype: float64

Die Astype-Problemumgehung funktioniert, ist jedoch für große Dateien (0,5 Millionen Zeilen) zu langsam. Irgendwelche anderen Vorschläge?
Student1

3
Das timedelta-Objekt hat Attribute für Tage und Sekunden ... Sie tun dies (df.fr-df.to) .dt.days * 24 + (df.fr-df.to) .dt.seconds / 3600
nitin

1
Vielen Dank! Dies funktionierte auch für mich zur Berechnung der Jahre (um das Alter zu ermitteln): df ['age'] = (df ['later_date'] - df ['geburtsdatum']). Astype ('timedelta64 [Y]')
Superduper

47

Das hat mich verrückt gemacht, da die .astype()obige Lösung für mich nicht funktioniert hat. Aber ich habe einen anderen Weg gefunden. Ich habe es nicht geplant oder so, könnte aber für andere da draußen funktionieren:

t1 = pd.to_datetime('1/1/2015 01:00')
t2 = pd.to_datetime('1/1/2015 03:30')

print pd.Timedelta(t2 - t1).seconds / 3600.0

... wenn du Stunden willst. Oder:

print pd.Timedelta(t2 - t1).seconds / 60.0

... wenn Sie Minuten wollen.


9
Ich hatte das gleiche Problem, aber bei Ihrer Lösung muss man vorsichtig sein, da Zeitunterschiede, die größer als ein Tag sind, ignoriert werden und separat berücksichtigt werden müssen
Hufeisen

39
Ich habe gerade herausgefunden, dass .total_seconds()das den Job für diejenigen macht, die es brauchen
Hufeisen

Merkwürdiger (ich bemerken später 4 Jahre), müssen Sie Pars verwenden ()für , .total_seconds()aber nicht.seconds
elPastor

5
  • Wie konvertiere ich meine Ergebnisse in nur Stunden und Minuten?
    • Die akzeptierte Antwort wird nur zurückgegeben days + hours. Minuten sind nicht enthalten.
  • Um eine Spalte mit Stunden und Minuten als hh:mmoder bereitzustellen x hours y minutes, sind zusätzliche Berechnungen und die Formatierung von Zeichenfolgen erforderlich.
  • Diese Antwort zeigt, wie Sie mithilfe von timedeltaMathematik entweder die Gesamtstunden oder die Gesamtminuten als Float erhalten. Sie ist schneller als die Verwendung.astype('timedelta64[h]')
  • Pandas Time Deltas Benutzerhandbuch
  • Pandas Zeitreihen- / Datumsfunktionalität Benutzerhandbuch
  • Python- timedeltaObjekte : Siehe unterstützte Operationen.
import pandas as pd

# test data from OP, with values already in a datetime format
data = {'to_date': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000'), pd.Timestamp('2014-01-23 10:07:47.660000')],
        'from_date': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000'), pd.Timestamp('2014-01-23 18:50:41.420000')]}

# test dataframe; the columns must be in a datetime format; use pandas.to_datetime if needed
df = pd.DataFrame(data)

# add a timedelta column if wanted. It's added here for information only
# df['time_delta_with_sub'] = df.from_date.sub(df.to_date)  # also works
df['time_delta'] = (df.from_date - df.to_date)

# create a column with timedelta as total hours, as a float type
df['tot_hour_diff'] = (df.from_date - df.to_date) / pd.Timedelta(hours=1)

# create a colume with timedelta as total minutes, as a float type
df['tot_mins_diff'] = (df.from_date - df.to_date) / pd.Timedelta(minutes=1)

# display(df)
                  to_date               from_date             time_delta  tot_hour_diff  tot_mins_diff
0 2014-01-24 13:03:12.050 2014-01-26 23:41:21.870 2 days 10:38:09.820000      58.636061    3518.163667
1 2014-01-27 11:57:18.240 2014-01-27 15:38:22.540 0 days 03:41:04.300000       3.684528     221.071667
2 2014-01-23 10:07:47.660 2014-01-23 18:50:41.420 0 days 08:42:53.760000       8.714933     522.896000

Andere Methoden

  • Ein Hinweis aus dem Podcast in "Andere Ressourcen" .total_seconds()wurde hinzugefügt und zusammengeführt, als der Hauptentwickler im Urlaub war, und wäre nicht genehmigt worden.
    • Dies ist auch der Grund, warum es keine anderen .total_xxMethoden gibt.
# convert the entire timedelta to seconds
# this is the same as td / timedelta(seconds=1)
(df.from_date - df.to_date).dt.total_seconds()
[out]:
0    211089.82
1     13264.30
2     31373.76
dtype: float64

# get the number of days
(df.from_date - df.to_date).dt.days
[out]:
0    2
1    0
2    0
dtype: int64

# get the seconds for hours + minutes + seconds, but not days
# note the difference from total_seconds
(df.from_date - df.to_date).dt.seconds
[out]:
0    38289
1    13264
2    31373
dtype: int64

Andere Ressourcen

%%timeit Prüfung

import pandas as pd

# dataframe with 2M rows
data = {'to_date': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000')], 'from_date': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000')]}
df = pd.DataFrame(data)
df = pd.concat([df] * 1000000).reset_index(drop=True)

%%timeit
(df.from_date - df.to_date) / pd.Timedelta(hours=1)
[out]:
43.1 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
(df.from_date - df.to_date).astype('timedelta64[h]')
[out]:
59.8 ms ± 1.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.