So ändern Sie das Datum / Uhrzeit-Format in Pandas

106

Mein Datenrahmen hat eine DOBSpalte (Beispielformat 1/1/2016), die standardmäßig in den Pandas-Typ 'Objekt' konvertiert wird:DOB object

Wenn Sie dies in das Datumsformat mit df['DOB'] = pd.to_datetime(df['DOB'])konvertieren, wird das Datum in: konvertiert 2016-01-26und dtypelautet : DOB datetime64[ns].

Jetzt möchte ich dieses Datumsformat in 01/26/2016oder in andere allgemeine Datumsformate konvertieren . Wie mache ich es?

Unabhängig von der Methode, die ich versuche, wird das Datum immer im 2016-01-26Format angezeigt.

Yo Ich
quelle
Suchen Sie eine Lösung, die nur unter Jupyter Notebook funktioniert? (in welchem ​​Fall verwenden Sie einen "Styler" pro Spalte) oder funktioniert es in einer einfachen Python-Konsole und in iPython?
smci

Antworten:

206

Sie können verwenden, dt.strftimewenn Sie datetimein andere Formate konvertieren müssen (beachten Sie jedoch, dass dann dtypeder Spalte object( string) lautet):

import pandas as pd

df = pd.DataFrame({'DOB': {0: '26/1/2016', 1: '26/1/2016'}})
print (df)
         DOB
0  26/1/2016 
1  26/1/2016

df['DOB'] = pd.to_datetime(df.DOB)
print (df)
         DOB
0 2016-01-26
1 2016-01-26

df['DOB1'] = df['DOB'].dt.strftime('%m/%d/%Y')
print (df)
         DOB        DOB1
0 2016-01-26  01/26/2016
1 2016-01-26  01/26/2016
jezrael
quelle
31
'strftime' konvertiert die datetime-Spalte in Unicode, um die Operation auf DOB1 anzuwenden. Wir müssen sie erneut in datetime konvertieren. Gibt es keine andere Möglichkeit zum Formatieren, ohne den Datentyp zu verlieren?
M. Zaman
@jezrael, gibt es eine bessere Lösung, die auch den Datentyp beibehält und die Daten nicht an eine Objektspalte zurückgibt? Das Problem ist, dass wenn versucht wird, es nach der Zeile 'df [' DOB1 '] = df [' DOB ']. Dt.strftime ('% m /% d /% Y ')' zu konvertieren, wie es in der Lösung vorgeschlagen wird darüber kehren die Daten zu ihrem ursprünglichen Format zurück.
Ausgestoßene
haha, wie kann ich das tun, wenn ich diese Spalte dann für .mergeeine Datetime-Spalte eines anderen Datenrahmens verwenden möchte? Ist es sinnvoll, die andere datetime-Spalte in eine Objektspalte zu konvertieren, um dies zu tun .merge?
Ausgestoßene
Ja, anscheinend stimme ich zu, aber mit "Nicht vorhanden :(" haben Sie mir gesagt, dass ich die Spalte nach dem Ändern des Formats nicht in datetime konvertieren kann, ohne das neue Format zu verlieren. Also?
Ausgestoßen
Ok, soweit ich .mergeweiß , kann dies immer noch korrekt durchgeführt werden, wenn beide Spalten Datums- / Uhrzeitspalten sind, auch wenn sie nicht genau das gleiche Format haben. Ist das richtig?
Ausgestoßener
21

Ändern des Formats, aber nicht des Typs:

df['date'] = pd.to_datetime(df["date"].dt.strftime('%Y-%m'))
Yanni Cao
quelle
Denken Sie daran, dass df ["Datum"] datetime64 sein sollte, bevor Sie dies tun
adhg
4
Nein! Angenommen, der ursprüngliche Wert eines Elements in der dateSpalte lautet " 26. November 2019". strftime()bedeutet "Zeichenfolge ab Zeit" , df["date"].dt.strftime('%Y-%m')wird also eine Zeichenfolge "2019-11" für dieses Element sein. Dann pd.to_datetime()wird diese Zeichenfolge wieder in das datetime64Format konvertiert, jetzt jedoch als " 1. November 2019"! Das Ergebnis ist also: Keine Formatänderung, sondern die Änderung des Datumswerts selbst!
MarianD
2
@MarianD: Alle Ihre Kommentare zu einzelnen Antworten sind nützlich, aber können Sie sie bitte in einem Rollup von "Fallstricke / Nicht tun" am Ende Ihrer Antwort zusammenfassen? Außerdem müssen Sie klar angeben, wo das Problem bei jedem dieser Daten liegt: Wenn eines der Eingabedaten nicht das erwartete Format aufweist, besteht die Gefahr, dass Ausnahmen ausgelöst werden oder das Datum entstellt wird. Einfach "Nein!" überall vermittelt das nicht.
smci
8

Der folgende Code hat bei mir anstelle des vorherigen funktioniert - probieren Sie es aus!

df['DOB']=pd.to_datetime(df['DOB'].astype(str), format='%m/%d/%Y')
Rishi Jain
quelle
2
Nein! Ihr format='%m/%d/%Y'Parameter dient zum Parsen einer Zeichenfolge, dh Sie sollen die Zeichenfolge in einem solchen Format bereitstellen (z "5/13/2019". B. ). Nichts mehr, keine Formatänderung. Es wird weiterhin als angezeigt 2019-05-13- oder es wird eine Ausnahme ausgelöst, wenn df['DOB'].astype(str)Elemente enthalten sind, die nicht in einem solchen Format vorliegen, z "2019-05-13". B. in einem Format .
MarianD
4

Im Vergleich zur ersten Antwort empfehle ich, zuerst dt.strftime () und dann pd.to_datetime () zu verwenden. Auf diese Weise wird weiterhin der Datentyp datetime angezeigt.

Beispielsweise,

import pandas as pd

df = pd.DataFrame({'DOB': {0: '26/1/2016 ', 1: '26/1/2016 '})
print(df.dtypes)

df['DOB1'] = df['DOB'].dt.strftime('%m/%d/%Y')
print(df.dtypes)

df['DOB1'] = pd.to_datetime(df['DOB1'])
print(df.dtypes)
user3512680
quelle
2
Dies funktioniert zumindest in meinem Fall nicht. Insbesondere wird die Spalte in den Datetime-Datentyp konvertiert, aber auch die Werte werden in das ursprüngliche Format konvertiert!
Ausgestoßener
Nein! Syntaxfehler (fehlende Klammer), in meiner Version von Pandas (0.25.1) ein anderer Syntaxfehler (dt.strftime () - kann nur .dt-Accessor mit datenzeitähnlichen Werten verwenden) - Sie verlassen sich auf den inhärenten Datentyp, jedoch in verschiedenen Versionen von Pandas die inhärenten Datentypen können unterschiedlich sein) und eine seltsame Logik - warum Datumszeit in Zeichenfolge und dann zurück in Datumszeit konvertieren ? Siehe meinen Kommentar zur Antwort von Rishi Jain.
MarianD
1

Der folgende Code ändert sich in den Typ 'datetime' und formatiert auch in der angegebenen Formatzeichenfolge. Funktioniert gut!

df['DOB']=pd.to_datetime(df['DOB'].dt.strftime('%m/%d/%Y'))
San
quelle
2
Ändern Sie es in diese:df['DOB']=pd.to_datetime(df['DOB']).dt.strftime('%m/%d/%Y')
John Doe
Nein! - Warum Datetime in String konvertieren und dann zurück in Datetime ? Siehe meine Kommentare zu anderen Antworten.
MarianD
1

Sie können dies versuchen, um das Datumsformat in TT-MM-JJJJ zu konvertieren:

df['DOB'] = pd.to_datetime(df['DOB'], dayfirst = True)
Ashu007
quelle
Nein! dayfirst=Trueist nur die Angabe einer Datumsanalysereihenfolge, z. B. wird diese ambivalente Datumszeichenfolge als "2-1-2019" als 2. Januar 2019 und nicht als 1. Februar 2019 analysiert. Nichts weiter, keine Änderung für die Ausgabeformatierung .
MarianD
1

Es gibt einen Unterschied zwischen dem Inhalt einer Datenrahmenzelle (ein Binärwert) und ihrer Darstellung (Anzeige) für uns Menschen.

Wenn Sie das Jupyter-Notizbuch zum Anzeigen Ihres Datenrahmens verwenden oder ihn in Form einer HTML-Datei präsentieren möchten (mit vielen idund classAttributen für weiteres CSS-Styling, wenn Sie dies wünschen), können Sie das Styling verwenden .

Ich nehme an, dass Ihre Spalte DOBbereits den Typ hatdatetime64 (Sie haben gezeigt, dass Sie wissen, wie Sie ihn erreichen können). Ich habe einen einfachen Datenrahmen (mit nur einer Spalte) vorbereitet, um Ihnen einige grundlegende Stile zu zeigen:

  • Nicht gestylt:

       df
          DOB
0  2019-07-03
1  2019-08-03
2  2019-09-03
3  2019-10-03
  • Styling als mm/dd/yyyy:

       df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})
          DOB
0  07/03/2019
1  08/03/2019
2  09/03/2019
3  10/03/2019
  • Styling als dd-mm-yyyy:

       df.style.format({"DOB": lambda t: t.strftime("%d-%m-%Y")}) 
          DOB
0  03-07-2019
1  03-08-2019
2  03-09-2019
3  03-10-2019

Achtung! Das zurückgebende Objekt ist KEIN Datenrahmen - es ist ein Objekt der Klasse. Weisen Sie es Styleralso nicht zurück zu df:

Tu das nicht:

df = df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})    # Don´t do this!

(Auf jeden Datenrahmen kann über seine .styleEigenschaft auf sein Styler-Objekt zugegriffen werden , und wir haben dieses df.styleObjekt geändert , nicht den Datenrahmen selbst.)


Warum zeigt Ihr Styler-Objekt (oder ein Ausdruck, der es zurückgibt), der als letzter Befehl in einer Jupyter-Notizbuchzelle verwendet wird, Ihre (gestaltete) Tabelle an und nicht das Styler-Objekt selbst?

Weil jedes Styler-Objekt über eine ._repr_html_()Rückrufmethode verfügt, die einen HTML-Code zum Rendern Ihres Datenrahmens zurückgibt (als schöne HTML-Tabelle).

Jupyter Notebook IDE ruft diese Methode automatisch auf, um Objekte zu rendern, die sie haben.


Ein Styler-Objekt verfügt auch über eine Methode render(), wenn Sie eine Zeichenfolge mit dem HTML-Code erhalten möchten (z. B. zum Veröffentlichen Ihres formatierten Datenrahmens im Web):

df_styler = df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})
HTML_string = df_styler.render()
MarianD
quelle
Es sei darauf hingewiesen, dass Styler-Code wie dieser unter ausgeführt werden soll und nur unter Jupyter-Notebooks wirksam wird und absolut keine Auswirkungen hat, wenn er in der Konsole oder in iPython ausgeführt wird . Das OP hat "unter Jupyter" nicht angegeben, daher kann dies je nach Einrichtung eine praktikable Lösung sein oder auch nicht. Viele Data Science-Codes werden kopiert und eingefügt, und die Jupyter-spezifischen Annahmen werden nicht explizit angegeben. Dann fragen sich die Leute, warum der Styler-Code "nicht funktioniert", wenn er in ihrer (Konsolen-) Umgebung ausgeführt wird.
smci
@smci, wird im zweiten Absatz meiner Antwort nicht ausdrücklich darauf hingewiesen? In Form einer bedingten ifAussage, die jedem Programmierer so bekannt ist? - Trotzdem danke für Ihren Kommentar, es kann für einige Leute hilfreich sein.
MarianD
nein das ist sehr unklar, auch begraben. Die ursprüngliche Frage vermutete nichts über Jupyter, und das OP und einige Benutzer haben möglicherweise nicht einmal Jupyter zur Verfügung. Ihre Antwort müsste fett gedruckt sagen , seine erste Zeile „Der folgende Ansatz (Styling) nur unter Jupyter Notebook arbeitet, und wird keinerlei Auswirkungen haben , wenn sie außerhalb Jupyter Notebook laufen“ . (In Data Science-Blogs und -Seiten sehe ich täglich Leute, die Jupyter-Code in Nicht-Jupyter-Umgebungen veröffentlichen und sich fragen, warum dies nicht funktioniert.)
smci
1
@smci, du hast mich überzeugt, ich habe diesen wichtigen Hinweis zu Beginn meiner Antwort hinzugefügt. Vielen Dank!
MarianD
Cool. Ich schlage außerdem vor, dass Sie alle (vielen) Fallstricke hinzufügen, die Sie bei den anderen Ansätzen "Konvertieren in String mit Strftime-dann-wieder-wieder-mit-pd.to_datetime" identifiziert haben. Zumindest muss erwähnt werden, dass Ausnahmen ausgelöst und abgefangen werden. Hat pd.to_datetime()auch die Argumente, um errors='raise'/'coerce'/'ignore', dayfirst, yearfirst, utc, exactzu steuern, wie präzise und ausnahmefreudig es ist und ob ungültige Ausgaben dazu gezwungen werden NaToder was. Was es in "realen" Datensätzen komplizierter macht, sind gemischte / fehlende / unvollständige Formate, Zeiten, Zeitzonen usw.; Ausnahmen sind nicht unbedingt schlechte Dinge.
smci