В датасете даты разного формата, как привести все к единому?
В основном даты формата YYYY-MM-DD, но есть и DD.MM.YYYY, как привести все даты к одному формату используя питон и пандас? Хочу чтоб все были формата YYYY-MM-DD, можно ли регулярками вытащить неверный формат, а потом каким то образом привести к нужному?
Ответы (2 шт):
используйте pandas.to_datetime , примерно так он работает:
pd.to_datetime(pd.Series(['12.31.2020','31-12-2020','31.12.2020','12-31-2020','2020-12-31']))
вывод:
0 2020-12-31
1 2020-12-31
2 2020-12-31
3 2020-12-31
4 2020-12-31
dtype: datetime64[ns]
В Pandas для парсинга дат в виде строк в datetime существует удобная функция pd.to_datetime(), как уже написал @SergFSM в своем ответе.
Но при работе с датами формата DD.MM.YYYY или DD-MM-YYYY есть одна тонкость - если оба числа (день месяца и номер месяца) не превышают 12, то pd.to_datetime() по умолчанию парсит первое число как номер месяца (в американском стиле):
In [452]: pd.to_datetime(["2021-09-21", "03.09.2020", "13.12.2020"])
Out[452]: DatetimeIndex(['2021-09-21', '2020-03-09', '2020-12-13'], dtype='datetime64[ns]', freq=None)
# NOTE: -----------------------------> ^^^^^^^^^^
Поэтому я бы сначала спарсил все даты формата DD.MM.YYYY, а потом все остальные:
df = pd.DataFrame({"date": ["2021-09-21", "03.09.2020", "13.12.2020", "04-12-20", "03/01/2000", "blah-blah"]})
исходный фрейм:
In [468]: df
Out[468]:
date
0 2021-09-21
1 03.09.2020 # 3 Sep 2020
2 13.12.2020
3 04-12-20 # 4 Dec 2020
4 03/01/2000 # <- `1 Mar 2000` записано в американском стиле
5 blah-blah
парсим даты формата DD.MM.YYYY:
mask = df["date"].str.contains("^\d{1,2}[.-]\d{1,2}[.-](?:\d{4}|\d{2})")
df.loc[mask, "date"] = pd.to_datetime(df.loc[mask, "date"], dayfirst=True, errors="coerce")
после этого парсим оставшиеся даты:
df.loc[~mask, "date"] = pd.to_datetime(df.loc[~mask, "date"], errors="coerce")
результат:
In [472]: df
Out[472]:
date
0 2021-09-21 00:00:00
1 2020-09-03 00:00:00
2 2020-12-13 00:00:00
3 2020-12-04 00:00:00
4 2000-03-01 00:00:00
5 NaT
Если у вас в данных нет данных формата MM/DD/YYYY, т.е. таких где номер месяца стоит первым числом, тогда решение будет значительно проще:
df.loc[:, "date"] = pd.to_datetime(df["date"], dayfirst=True, errors="coerce")