【问题标题】:Extract and sort dates from Python dataframe using regex使用正则表达式从 Python 数据框中提取和排序日期
【发布时间】:2018-01-12 06:37:21
【问题描述】:

我正在研究一个由数千(行)字符串表达式组成的单列熊猫数据框。每个字符串可能包含不同格式的“日期”信息,例如:

05/10/2001; 05/10/01; 5/10/09; 6/2/01
May-10-2001; May 10, 2010; March 25, 2001; Mar. 25, 2001; Mar 25 2001;
25 Mar 2001; 25 March 2001; 25 Mar. 2001; 25 March, 2001
Mar 25th, 2001; Mar 25th, 2001; Mar 12nd, 2001
Feb 2001; Sep 2001; Oct 2001
5/2001; 11/2001
2001; 2015

以几个字符串为例:

df[0] he plans to depart on 6/12/95
df[1] as of Mar. 23rd, 2011, the board decides that...
df[2] the 12-28-01 record shows...

我想在 df 之后使用 findall() 函数,以便 df.str.findall(r'') 提取日期元素:

[0] 6/12/95
[1] Mar. 23rd, 2011
[2] 12-28-01

从原始字符串,然后是一些“排序”命令行,以按时间顺序按索引对提取的日期进行排序,以便输出看起来像

[0] 1
[1] 3
[2] 2

我(暂时)使用以下函数

df.str.findall(r'(?:\d{2} )?(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* (?:\d{2}, )?\d{4}')

但不知道如何处理

(1) 数字后序号:st, th, nd

(2) 偶尔出现的“.”代表缩写的值,以及

(3) 斜线 (/) 和连字符 (-)

一次性使用正则表达式 final 函数。

此外,在所有提取工作完成后,我想用它们各自的索引(即 1、2、3、...、n)按时间顺序对它们进行排序。但是我目前对正则表达式的了解不足以了解 Python 如何按时间顺序对这些不同的日期格式进行排序。

如果有人能为此提供一些关于 .findall() 函数的方便技巧或解释排序日期表达式的机制,将不胜感激。

【问题讨论】:

  • 请举例说明表达式应该匹配什么以及应该捕获什么
  • 我会将其添加到编辑后的文本中。感谢您解决这个问题。
  • 我认为这真的很难,实际上不可能在一个 .findall() 命令中提取各种日期格式。我想知道是否可以为每种日期格式一个一个地执行此操作,将它们堆叠在一起,最后使用 .to_datetime() 将它们转换为相同的格式“yyyy-mm-dd”?

标签: python regex date findall


【解决方案1】:

dateutil.parser.parse 可以帮助您避免使用正则表达式 - 在这里这样做肯定是件好事。

它基本上接受一个字符串并尝试在datetime 对象中解析它,这很棒,因为datetime 可以轻松排序。

from dateutil.parser import parse

data = """05/10/2001; 05/10/01; 5/10/09; 6/2/01
May-10-2001; May 10, 2010; March 25, 2001; Mar. 25, 2001; Mar 25 2001;
25 Mar 2001; 25 March 2001; 25 Mar. 2001; 25 March, 2001
Mar 25th, 2001; Mar 25th, 2001; Mar 12nd, 2001
Feb 2001; Sep 2001; Oct 2001
5/2001; 11/2001
2001; 2015"""

# Parse data into list of strings
data = data.replace('\n', ';').split(';')

dates = []
for line in data:
    try:
        dates.append(parse(line))
    except TypeError:
        # it's not parsable
        pass

print list(sorted(dates))

截断输出:

[datetime.datetime(2001, 2, 4, 0, 0), datetime.datetime(2001, 3, 12, 0, 0), datetime.datetime(2001, 3, 25, 0, 0), datetime.datetime(2001, 3, 25, 0, 0) ...]

如您所见,您赢了两分:

  1. 对日期时间对象进行排序真的很容易
  2. 您不必相信任何冗长而复杂的正则表达式模式就可以知道字符串是否为日期,parse 为您完成

【讨论】:

  • 您好,感谢您的回复。我在我的编辑器上试验了您的代码,它返回了一条错误消息,指出“行”不可解析。此外,所需的输出格式应该是我在问题文本中间列出的格式。
  • 你能给我这个错误吗(完整的回溯)?
  • ------------------------------------------ --------------------------------- ValueError Traceback(最近一次调用最后)() 15 for line in data: 16 try: ---> 17 dates.append(parse(line)) 18 except TypeError: 19 # it's not parsable
  • 我同意 dateparser.parse() 可能是将日期时间转换为人类可读格式的直接方法,但对我来说最难的部分是让这个函数在数千行 "字符串”在单列熊猫数据框中。
  • 问题的复杂性与您想要支持的不同格式的数量成正比。一个不错的选择可能是拥有一组可以从文本中提取日期字符串的正则表达式,然后使用此库将它们转换为日期时间对象,以便您可以更轻松地处理它们。
【解决方案2】:

我会尝试使用以下两个模块。 dateutil 在这个答案中:

Extracting date from a string in Python

和/或日期解析器:

https://dateparser.readthedocs.io/en/latest/

【讨论】:

  • 我在两个小时前已经阅读了这两个小时,但仍然无法将它们应用于具有数十种不同日期时间格式的 pandas 数据框。因此,这个线程中的问题。我想一旦我能够从数据框中的每一行文本中提取日期时间元素,“排序”的事情就应该很容易了。
【解决方案3】:

试试这个 """(r'(?:\d{1,2}[ ][/-])?(?:(?:Jan|Feb|Mar|Apr|May|Jun|Jul |Aug|Sep|Oct|Nov|Dec)[az]* )?(?:\d{1,2}[/-])?\d{2,4}')"""

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 2020-09-21
    • 1970-01-01
    • 2020-09-13
    • 2017-05-13
    • 2023-02-04
    • 2015-01-12
    相关资源
    最近更新 更多