【问题标题】:How can I tweak this regex for detecting correct date format in my dataframe?如何调整此正则表达式以在我的数据框中检测正确的日期格式?
【发布时间】:2020-08-16 16:33:42
【问题描述】:

如果我有这个数据框:

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。

有什么想法吗?

【问题讨论】:

  • [0-1]?\d[-\/]\d{4}可以吗
  • 请检查以下答案。如果没有帮助您,请提供反馈,否则,请考虑接受对您有用的答案。
  • 因为你有一个dataframe 标签,我认为my answer 与熊猫方法是相关的。

标签: python regex python-3.x dataframe


【解决方案1】:

我建议使用自定义 digit 边界((?<!\d)lookbehind 和 (?!\d)lookahead)以确保您只匹配您选择的数字并确保您匹配 years,而不仅仅是像 9873(?:19|20)\d{2} 这样的 4 位数字,带有交替运算符 + 任意两位数字的非捕获组。日期可以像Jan's answer 一样匹配,使用(?:0?[1-9]|1[0-2]) 模式。

使用str.extract 提取日期后,您可以使用pd.to_datetime 将它们转换为日期时间。

使用.fillna(),您可以处理不匹配的条目(我在下面的代码中将它们保留为空)。

正则表达式是

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

请参阅regex demo。详情:

  • (?&lt;!\d) - 如果紧靠当前位置的左侧有一个数字,则匹配失败的负向后查找
  • ((?:0?[1-9]|1[0-2])-(?:19|20)\d{2}) - 捕获组 1(str.extract 必需):
    • (?:0?[1-9]|1[0-2]) - 一个可选的0 和一个从19 的数字,或1 然后01 或2(so, numbers from1to12`)
    • - - 一个连字符
    • (?:19|20)\d{2} - 1920 然后是任意 2 位数字
  • (?!\d) - 如果在当前位置的右侧有一个数字,则匹配失败。

完整的sn-p:

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         

【讨论】:

  • 这太完美了!我正在练习这些表达式,所以我有一个问题要问:如果我想要另一个没有可选 0 的正则表达式,我会删除 '?:0?'部分?
  • @JTHDR 如果您不允许可选的0,是的,只需删除0?
【解决方案2】:

试试这个正则表达式:\b(0?[1-9]|1[0-2])[-/]\d{4}\b

Demo这里

【讨论】:

    【解决方案3】:

    你可以使用

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

    a demo on regex101.com


    请注意,由于这是一个常见问题,因此您可以使用 module called datefinder
    import datefinder
    matches = datefinder.find_dates(string_with_dates)
    

    在内部,它也使用正则表达式,如果你想看代码,see their github repo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      • 2011-08-13
      • 2020-01-13
      • 1970-01-01
      相关资源
      最近更新 更多