Как определить даты и преобразовать их в тип данных datetime64 - PullRequest
0 голосов
/ 02 апреля 2019

Я читаю данные из CSV с pandas.read_csv.Один из столбцов содержит информацию о дате в разных форматах (без стандарта ISO 8601 и т. П.).Я хочу убедиться, что Панды могут определять формат даты, не требуя дополнительного ввода от пользователя.Если честно, я не совсем уверен, с чего начать.Я знаю, что Pandas может infer_datetime_format, однако он не улавливает все варианты данных или может вызвать ошибку.

Мои наборы данных содержат несколько миллионов строк, поэтому процесс может занять довольно много времени.Моя идея состояла в том, чтобы загрузить только первые 100 строк (nrows=100), а затем позволить функции определять формат даты.Из наборов данных, которые я видел до сих пор, это могут быть дд-мм-гг, дд-мм-гггг, гггг-мм-дд (и различные варианты с разделителями .-), 19 января, январь 2019 г., 1 января 2019 г. и т. Д.Также у меня есть текст на английском (декабрь) и немецком (декабрь).

Я подумал о том, чтобы запустить что-то вроде цикла for для каждого элемента в столбце, подготовить дела в разных форматах, возможно, в tryexcept заблокировать и позволить Pyton определить правильный формат для первых 100 записей.(построить разные случаи с форматами даты из: https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior)

Имеет ли такой подход смысл? Или как бы вы поступили? Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

pd.to_datetime может быть на порядок медленнее, если вы попытаетесь определить формат. В смешанных форматах вы можете попытаться проанализировать его несколько раз:

import pandas as pd
from functools import reduce
                           # dd-mm-yy    dd-mm-YYYY    YYYY-mm-dd
df = pd.DataFrame({'date': ['12-01-01', '12-01-2001', '2001-07-05',
                            'Jan 19', 'January 2019', '1 January 2019']})

Код:

formats = ['%d-%m-%y', '%d-%m-%Y', '%Y-%m-%d', '%b %y', '%B %Y', '%d %B %Y']
reduce(lambda l,r: l.combine_first(r), 
       [pd.to_datetime(df.date, format=fmt, errors='coerce') for fmt in formats])

0   2001-01-12
1   2001-01-12
2   2001-07-05
3   2019-01-01
4   2019-01-01
5   2019-01-01
Name: date, dtype: datetime64[ns]

В общем случае pd.to_datetime может гибко анализировать большинство этих форматов, если указать dayfirst. Хотя это все равно будет медленнее, чем попытка несколько раз проанализировать его с указанными форматами.

pd.to_datetime(df.date, errors='coerce', dayfirst=True)
#0   2001-01-12
#1   2001-01-12
#2   2001-07-05
#3          NaT
#4   2019-01-01
#5   2019-01-01
#Name: date, dtype: datetime64[ns]

df = pd.concat([df]*10000, ignore_index=True)
%timeit reduce(lambda l,r: l.combine_first(r), [pd.to_datetime(df.date, format=fmt, errors='coerce') for fmt in formats])
#287 ms ± 2.35 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit pd.to_datetime(df.date, errors='coerce', dayfirst=True)
#5.79 s ± 36.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Таким образом, вы все равно выигрываете, даже пытаясь разобрать его несколько раз, плюс вы не пропустите некоторые нестандартные форматы.

0 голосов
/ 02 апреля 2019

Вы можете попробовать dateparser , который поддерживает синтаксический анализ дат на нескольких языках.

Из их документации:

>>> # parsing ambiguous date
>>> parse('02-03-2016')  # assumes english language, uses MDY date order
datetime.datetime(2016, 3, 2, 0, 0)
>>> parse('le 02-03-2016')  # detects french, uses DMY date order
datetime.datetime(2016, 3, 2, 0, 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...