Behalten Sie bei Verwendung von pandas.to_datetime nur den Datumsteil bei


201

Ich verwende pandas.to_datetime, um die Daten in meinen Daten zu analysieren. Pandas stellen standardmäßig die Daten mit dar datetime64[ns], obwohl die Daten alle nur täglich sind. Ich frage mich, ob es eine elegante / clevere Möglichkeit gibt, die Daten in datetime.dateoder datetime64[D]so zu konvertieren , dass beim Schreiben der Daten in CSV die Daten nicht angehängt werden 00:00:00. Ich weiß, dass ich den Typ manuell Element für Element konvertieren kann:

[dt.to_datetime().date() for dt in df.dates]

Aber das ist wirklich langsam, da ich viele Zeilen habe und es den Zweck der Verwendung irgendwie zunichte macht pandas.to_datetime. Gibt es eine Möglichkeit, dtypedie gesamte Spalte auf einmal zu konvertieren ? Oder unterstützt alternativ pandas.to_datetimeeine Präzisionsspezifikation, damit ich den Zeitteil während der Arbeit mit täglichen Daten loswerden kann?


2
Ich kenne keinen guten Weg, df.dates.apply(lambda x: x.date()) sollte aber zumindest etwas schneller sein. Werfen Sie
root


1
Ich würde diese beiden Fragen als unterschiedlich betrachten. Das mögliche Duplikat, auf das Sie sich beziehen, zielt darauf ab, den Datumsteil und den Zeitteil von einer Datums- / Uhrzeitspalte zu trennen. Diese Frage wird durch die gleichzeitige Konvertierung der gesamten Spalte motiviert. Stellen Sie sich vor, Sie haben einen Datenrahmen mit 20 Spalten, die Datumsangaben darstellen. Sie möchten nicht angeben, welche Spalten in csv geschrieben werden sollen, wie in der anderen Frage vorgeschlagen.

1
Dies wird derzeit nicht unterstützt (@root weist auf die mögliche Verbesserung hin). Wozu dient dies beim Schreiben in csv?
Jeff

3
Nun, oft müssen wir Daten in CSV-Dateien schreiben, um von anderen Programmen gelesen zu werden. Die redundante 00:00:00 erschwert die Verarbeitung im Allgemeinen nur, insbesondere wenn ich mit rein täglichen Daten arbeite.

Antworten:


284

Seit der Version 0.15.0kann dies jetzt einfach durchgeführt werden, indem .dtnur auf die Datumskomponente zugegriffen wird:

df['just_date'] = df['dates'].dt.date

Das obige gibt einen datetime.datedtype zurück. Wenn Sie einen haben möchten, datetime64können Sie nur normalizedie Zeitkomponente auf Mitternacht setzen, sodass alle Werte auf Folgendes gesetzt werden 00:00:00:

df['normalised_date'] = df['dates'].dt.normalize()

Dadurch bleibt der Typ d erhalten datetime64, auf dem Display wird jedoch nur der dateWert angezeigt .


33

Einfache Lösung:

df['date_only'] = df['date_time_column'].dt.date

Nur eine Warnung, dies ändert den Typ in Objekt. Sie müssen also einen Typ eingeben ('datetime64'), um die Konsistenz zu gewährleisten.
Misantroop

25

Während ich EdChums Antwort, die die direkteste Antwort auf die vom OP gestellte Frage ist, positiv bewertet habe, löst sie das Leistungsproblem nicht wirklich (sie basiert immer noch auf Python datetime basiert Objekten, und daher wird jede Operation an ihnen nicht vektorisiert - das heißt, es wird langsam sein).

Eine leistungsstärkere Alternative ist die Verwendung df['dates'].dt.floor('d'). Genau genommen wird nicht nur der Datumsteil beibehalten, sondern nur die Zeit auf 00:00:00. Aber es funktioniert wie vom OP gewünscht, wenn zum Beispiel:

  • Drucken auf dem Bildschirm
  • Speichern auf CSV
  • mit der Spalte zu groupby

... und es ist viel effizienter, da die Operation vektorisiert ist.

EDIT: in der Tat, die Antwort der OPs bevorzugt hätte wahrscheinlich „neuere Versionen von pandasnicht nicht die Zeit zu csv schreiben , wenn es 00:00:00für alle Beobachtungen“.


Leider to_jsonschreibt noch das volle 00:00:00.
IanS

@IanS meinst du bei der Verwendung date_format='iso'?! Standardmäßig werden nur Sekunden seit der Epoche ausgegeben.
Pietro Battiston

Ja das meinte ich.
IanS

Dies ist schneller als dt.normalize()bei Serien, die länger als einige hundert Elemente sind.
C8H10N4O2

15

Pandas DatetimeIndexund Serieshaben eine Methode namens normalize, die genau das tut, was Sie wollen.

Sie können mehr darüber in dieser Antwort lesen .

Es kann als verwendet werden ser.dt.normalize()


14

Pandas V0.13 +: Verwenden Sie to_csvmit date_formatParameter

Vermeiden Sie nach Möglichkeit, Ihre datetime64[ns]Serie in eine objectdtype-Objektreihe zu konvertieren datetime.date. Letzteres wird häufig unter Verwendung pd.Series.dt.datevon Zeigern gespeichert und ist im Vergleich zu einer reinen NumPy-basierten Reihe ineffizient.

Da Ihr Anliegen beim Schreiben in CSV das Format ist , verwenden Sie einfach den date_formatParameter von to_csv. Beispielsweise:

df.to_csv(filename, date_format='%Y-%m-%d')

Formatierungskonventionen finden Sie in den Python- strftimeAnweisungen .


8

Dies ist eine einfache Möglichkeit, das Datum zu extrahieren:

import pandas as pd

d='2015-01-08 22:44:09' 
date=pd.to_datetime(d).date()
print(date)

Das OP verwendet bereits die .date () -Methode in seiner Frage, daher beantwortet diese Lösung ihre Frage nicht, aber ich fand es nützlich, ein einfaches Beispiel für die Verwendung der date () -Methode nur als Referenz zu sehen.
Nic Scozzaro

5

Konvertieren in datetime64[D]:

df.dates.values.astype('M8[D]')

Wenn Sie dies einer DataFrame-Spalte neu zuweisen, wird es wieder auf [ns] zurückgesetzt.

Wenn Sie tatsächlich wollten datetime.date:

dt = pd.DatetimeIndex(df.dates)
dates = np.array([datetime.date(*date_tuple) for date_tuple in zip(dt.year, dt.month, dt.day)])

3
Wenn Sie Astype ('M8 [D]') verwenden, werden fehlende Werte in das Ursprungsdatum 1970-1-1 umgewandelt. Wahrscheinlich ist es heutzutage besser, nur pandas.to_datetime () zu verwenden.
Stewbaca

1
Hinweis für alle, die das datetime-Modul routinemäßig als dteinschließen, überschreibt dieses Antwort-Snipet dieses Modul! @ Dale-Jung, könnte vielleicht die Zeile zu etwas wie dt_index ändern
yeliabsalohcin

Ich finde auch ein Problem, bei dem df.loc[date]der Index beim nächsten Versuch, eine neue Zeile über die Methode hinzuzufügen , auf einen Zeitstempel zurückgesetzt wird, was bedeutet, dass nachfolgende Vergleiche nicht mehr funktionieren
yeliabsalohcin

3

Geben Sie einfach eine aktuellere Antwort, falls jemand diesen alten Beitrag sieht.

Durch Hinzufügen von "utc = False" bei der Konvertierung in datetime wird die Zeitzonenkomponente entfernt und nur das Datum in einem datetime64 [ns] -Datentyp beibehalten.

pd.to_datetime(df['Date'], utc=False)

Sie können es in Excel speichern, ohne den Fehler "ValueError: Excel unterstützt keine Datumsangaben mit Zeitzonen. Stellen Sie sicher, dass die Datumsangaben keine Zeitzone enthalten, bevor Sie in Excel schreiben."

Geben Sie hier die Bildbeschreibung ein


Dies schlägt aus irgendeinem Grund fehl, nachdem Sie eine Aggregatfunktion auf die Spalte angewendet haben.
RaphX

0

Ich wollte in der Lage sein, den Typ für eine Reihe von Spalten in einem Datenrahmen zu ändern und dann die Uhrzeit zu entfernen, die den Tag hält. rund (), boden (), decken () alle arbeiten

df[date_columns] = df[date_columns].apply(pd.to_datetime)
df[date_columns] = df[date_columns].apply(lambda t: t.dt.floor('d'))
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.