В датасете даты разного формата, как привести все к единому?

В основном даты формата YYYY-MM-DD, но есть и DD.MM.YYYY, как привести все даты к одному формату используя питон и пандас? Хочу чтоб все были формата YYYY-MM-DD, можно ли регулярками вытащить неверный формат, а потом каким то образом привести к нужному?


Ответы (2 шт):

Автор решения: SergFSM

используйте 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]
→ Ссылка
Автор решения: MaxU

В 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")
→ Ссылка