首页 > 解决方案 > 如何调整此正则表达式以在我的数据框中检测正确的日期格式?

问题描述

如果我有这个数据框:

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

我想在以下条件下检测 dob 列中的日期(mm-yyyy):

  1. 年份不能超过 4 个字符(当然必须是 int)
  2. 月份可以是一位数或两位数(例如:02、2、12、11、10、9、09:都可以),但如果是两位数,则第一个字符只能是 0-1 和第二个 0-9

到目前为止,我有这个正则表达式:

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

但我没有得到我想要的结果。在我的条件下,我不应该在我的数据框中检测到 kim 或 jane。

有任何想法吗?

标签: pythonregexpython-3.xdataframe

解决方案


我建议使用自定义数字边界((?<!\d)lookbehind 和(?!\d)lookahead)来确保您只匹配您选择的数字并确保您匹配年份,而不仅仅是 4 位数字,例如9873带有(?:19|20)\d{2}交替运算符 + 任何两位数字的非捕获组。天数可以与Jan 的答案中的(?: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)- 如果紧靠当前位置的左侧有一个数字,则匹配失败的负向后查找
  • ((?:0?[1-9]|1[0-2])-(?:19|20)\d{2})- 捕获组 1(需要str.extract):
    • (?:0?[1-9]|1[0-2])- 一个可选0的数字,从to19then1或2 1 12`)01(so, numbers fromto
    • -- 一个连字符
    • (?:19|20)\d{2}-1920,然后是任意 2 位数字
  • (?!\d)- 如果在当前位置的右侧有一个数字,则匹配失败的负前瞻。

完整片段:

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         

推荐阅读