Wie kann ich eine DataFrame-Spalte mit Zeichenfolgen (im dd/mm/yyyy-Format) in datetime-Datentyp konvertieren?
Antworten
Zu viele Anzeigen?Der einfachste Weg ist die Verwendung von to_datetime
:
df['col'] = pd.to_datetime(df['col'])
Es bietet auch ein dayfirst
Argument für europäische Zeiten (aber Vorsicht, das ist nicht streng).
Hier ist es in Aktion:
In [11]: pd.to_datetime(pd.Series(['05/23/2005']))
Out[11]:
0 2005-05-23 00:00:00
dtype: datetime64[ns]
Sie können ein spezifisches Format übergeben:
In [12]: pd.to_datetime(pd.Series(['05/23/2005']), format="%m/%d/%Y")
Out[12]:
0 2005-05-23
dtype: datetime64[ns]
Wenn Ihre Datums-Spalte einen String im Format '2017-01-01' ist, können Sie pandas astype verwenden, um sie in ein Datetime-Format umzuwandeln.
df['date'] = df['date'].astype('datetime64[ns]')
oder verwenden Sie datetime64[D], wenn Sie eine Tagesgenauigkeit und keine Nanosekunden möchten
print(type(df_launath['date'].iloc[0]))
ergibt
dasselbe wie bei Verwendung von pandas.to_datetime
Sie können es mit anderen Formaten als '%Y-%m-%d' ausprobieren, aber zumindest funktioniert dies.
Wenn Sie eine Mischung von Formaten in Ihrem Datum haben, vergessen Sie nicht, infer_datetime_format=True
zu setzen, um das Leben einfacher zu machen.
df['date'] = pd.to_datetime(df['date'], infer_datetime_format=True)
Quelle: pd.to_datetime
oder wenn Sie einen individuellen Ansatz wollen:
def autoconvert_datetime(value):
formats = ['%m/%d/%Y', '%m-%d-%y'] # Formate, die ausprobiert werden sollen
result_format = '%d-%m-%Y' # Ausgabeformat
for dt_format in formats:
try:
dt_obj = datetime.strptime(value, dt_format)
return dt_obj.strftime(result_format)
except Exception as e: # wirft eine Ausnahme, wenn das Format nicht übereinstimmt
pass
return value # lass es so, wenn es nicht übereinstimmt
df['date'] = df['date'].apply(autoconvert_datetime)
Mehrere Datumszeit-Spalten
Wenn Sie mehrere String-Spalten in Datumszeiten umwandeln möchten, dann ist es hilfreich, apply()
zu verwenden.
df[['date1', 'date2']] = df[['date1', 'date2']].apply(pd.to_datetime)
Sie können Parameter als kwargs an to_datetime
übergeben.
df[['start_date', 'end_date']] = df[['start_date', 'end_date']].apply(pd.to_datetime, format="%m/%d/%Y")
Wenn Sie apply
ohne Angabe von axis
verwenden, werden die Werte dennoch vektoriell für jede Spalte umgewandelt. apply
wird hier benötigt, da pd.to_datetime
nur auf eine einzelne Spalte angewendet werden kann. Wenn es auf mehrere Spalten angewendet werden muss, bestehen die Optionen entweder darin, eine explizite for-Schleife
zu verwenden oder es an apply
zu übergeben. Andererseits sollte vermieden werden, pd.to_datetime
mit apply
auf eine Spalte aufzurufen (z.B. df['date'].apply(pd.to_datetime))
, da dies nicht vektorisiert wäre.
Verwenden Sie format=
zur Beschleunigung
Wenn die Spalte eine Zeitkomponente enthält und Sie das Format des Datums/der Zeit kennen, führt das explizite Übergeben des Formats zu einer erheblichen Beschleunigung der Umwandlung. Bei einer Spalte, die nur das Datum enthält, gibt es kaum einen Unterschied. In meinem Projekt betrug der Unterschied für eine Spalte mit 5 Millionen Zeilen riesig: ~2,5 Min vs. 6 Sek.
Es stellt sich heraus, dass das explizite Angeben des Formats etwa 25x schneller ist. Das folgende Laufzeitdiagramm zeigt, dass es je nach Übermittlung des Formats eine enorme Leistungslücke gibt.
Der Code, der zur Erstellung des Diagramms verwendet wurde:
import perfplot
import random
mdYHM = range(1, 13), range(1, 29), range(2000, 2024), range(24), range(60)
perfplot.show(
kernels=[lambda x: pd.to_datetime(x), lambda x: pd.to_datetime(x, format='%m/%d/%Y %H:%M')],
labels=['pd.to_datetime(x)', "pd.to_datetime(x, format='%m/%d/%Y %H:%M')"],
n_range=[2**k for k in range(19)],
setup=lambda n: pd.Series([f"{m}/{d}/{Y} {H}:{M}"
for m,d,Y,H,M in zip(*[random.choices(e, k=n) for e in mdYHM])]),
equality_check=pd.Series.equals,
xlabel='len(df)'
)
- See previous answers
- Weitere Antworten anzeigen