Как я могу настроить это регулярное выражение для определения правильного формата даты в моем фрейме данных? - PullRequest
2 голосов
/ 02 мая 2020

если бы у меня был этот кадр данных:

df:
name  dob
will  05-2020
John  4-2020
James 07-1999
Rob   2-2001
kim   1-20202020
Jane  112-2020

Я хочу определить даты (мм-гггг) в столбце dob при следующих условиях:

  1. Год не может быть длиннее 4 символов (обязательно должно быть int)
  2. месяц может быть один ди git или два (примеры: 02, 2, 12, 11, 10, 9, 09: все приемлемо) но если его две цифры, первый символ может быть только от 0-1, а второй от 0-9

У меня пока есть это регулярное выражение:

r'\d{2}[-/]\d{4}'

но я не получаю результат, который я хочу. в моих условиях я не должен обнаруживать Ким или Джейн в моем фрейме данных.

есть идеи?

Ответы [ 3 ]

1 голос
/ 02 мая 2020

Попробуйте с этим регулярным выражением: \b(0?[1-9]|1[0-2])[-/]\d{4}\b

Демо здесь

1 голос
/ 02 мая 2020

Я предлагаю использовать пользовательские di git границы ((?<!\d) lookbehind и (?!\d) lookahead), чтобы убедиться, что вы соответствуете только числам по вашему выбору, и убедитесь, что вы соответствуете годам , а не только 4-значные git числа, такие как 9873 с (?:19|20)\d{2} группой без захвата с оператором чередования + любые две цифры. Дни можно сопоставить, как в ответе Яна , с шаблоном (?:0?[1-9]|1[0-2]).

После извлечения дат с помощью str.extract вы можете привести их к дате с помощью pd.to_datetime.

С помощью .fillna() вы можете манипулировать записями без совпадений (я оставил их пустыми в приведенном ниже коде).

Регулярное выражение равно

(?<!\d)((?:0?[1-9]|1[0-2])-(?:19|20)\d{2})(?!\d)

См. Регулярное выражение демо . Детали:

  • (?<!\d) - отрицательный вид сзади, который не соответствует совпадению, если непосредственно слева от текущего местоположения есть ди git
  • ((?:0?[1-9]|1[0-2])-(?:19|20)\d{2}) - Группа захвата 1 (требуется для str.extract):
    • (?:0?[1-9]|1[0-2]) - необязательно 0 и ди git от 1 до 9 или 1, а затем 0 , 1 или 2 (so, numbers from 1 to 12`)
    • - - дефис
    • (?:19|20)\d{2} - 19 или 20, а затем любые 2 цифры
  • (?!\d) - отрицательный прогноз, который не дает совпадения, если сразу справа от текущего местоположения есть ди git.

Полный фрагмент:

import pandas as pd
df = pd.DataFrame()
data = { 'dob': ['will\t05-2020', 'John\t4-2020', 'James\t07-1999', 'Rob\t2-2001','kim\t1-20202020','Jane\t112-2020']}
df = pd.DataFrame(data)
df['Date'] = df['dob'].str.extract(r'(?<!\d)((?:0?[1-9]|1[0-2])-(?:19|20)\d{2})(?!\d)').fillna("")
df['Date'] = pd.to_datetime(df['Date'], format='%m%Y', errors='ignore')

Вывод:

>>> df
               dob     Date
0    will\t05-2020  05-2020
1     John\t4-2020   4-2020
2   James\t07-1999  07-1999
3      Rob\t2-2001   2-2001
4  kim\t1-20202020         
5   Jane\t112-2020         
1 голос
/ 02 мая 2020

Вы можете использовать

\b(?:0?[1-9]|1[0-2])-\d{4}\b

См. демо на regex101.com .


Обратите внимание, поскольку это частый вопрос, есть модуль с именем datefinder, который вы можете использовать:
import datefinder
matches = datefinder.find_dates(string_with_dates)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...