无法使用正则表达式将命名组拆分为日期格式的列

问题描述

我正在尝试从作为熊猫系列对象读取的文本中提取日期格式。我已经成功编写了用于提取所有复杂日期格式的正则表达式。

但是在将组提取为命名组时,我面临着巨大的痛苦。主要问题是我在表达中使用了非捕获组,因此很难将它们作为命名组。

我需要的输出是数据框的形式,其列为提取的整个日期,后跟年份,月份和日期。示例输入如下

df5 = pd.Series(
    ["04/20/2009","04/20/09","4/20/09","4/3/09","Mar-20-2009","Mar 20,2009","march 20,"Mar. 20,"Mar 20 2009","20 Mar 2009","20 march 2009","20 Mar. 2009","20 march,"Mar 20th,"Mar 21st,"Mar 22nd,"Feb 2009","Sep 2009","Oct 2010","6/2008","12/2009","2009","2010"])

我以前提取的表达式是

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

我无法执行将日期拆分为年,月和日的后续步骤。我尝试使用 re.compile和re.search 进行拆分,但是我无法理解它引发的错误

TypeError:无法在类似字节的对象上使用字符串模式。

任何建议都将受到欢迎。 附注:我从类似的问题中观察了很多来自stackoverflow的类似性质的问题 sample 1sample 2。我要提取的日期格式非常复杂,并且已经尝试了将近一周的时间,因此请不要轻易将其作为重复项来解决

解决方法

回答实际目标:

您可以使用预先存在的功能来代替正则表达式吗?如果是这样,则只需使用pd.to_datetime。它成功解析了您的样本数据

pd.to_datetime(df5)
# outputs:
0    2009-04-20
1    2009-04-20
2    2009-04-20
3    2009-04-03
4    2009-03-20
5    2009-03-20
6    2009-03-20
7    2009-03-20
8    2009-03-20
9    2009-03-20
10   2009-03-20
11   2009-03-20
12   2009-03-20
13   2009-03-20
14   2009-03-21
15   2009-03-22
16   2009-02-01
17   2009-09-01
18   2010-10-01
19   2008-06-01
20   2009-12-01
21   2009-01-01
22   2010-01-01
dtype: datetime64[ns]

要提取日期成分,可以使用.dt访问器

完整解决方案示例,产生一个数据框:

pd.concat([
  df5.rename('date_str'),pd.to_datetime(df5).dt.year.rename('year'),pd.to_datetime(df5).dt.month.rename('month'),pd.to_datetime(df5).dt.date.rename('date')
],axis=1)

          date_str  year  month        date
0       04/20/2009  2009      4  2009-04-20
1         04/20/09  2009      4  2009-04-20
2          4/20/09  2009      4  2009-04-20
3           4/3/09  2009      4  2009-04-03
4      Mar-20-2009  2009      3  2009-03-20
5     Mar 20,2009  2009      3  2009-03-20
6   March 20,2009  2009      3  2009-03-20
7    Mar. 20,2009  2009      3  2009-03-20
8      Mar 20 2009  2009      3  2009-03-20
9      20 Mar 2009  2009      3  2009-03-20
10   20 March 2009  2009      3  2009-03-20
11    20 Mar. 2009  2009      3  2009-03-20
12  20 March,2009  2009      3  2009-03-20
13  Mar 20th,2009  2009      3  2009-03-20
14  Mar 21st,2009  2009      3  2009-03-21
15  Mar 22nd,2009  2009      3  2009-03-22
16        Feb 2009  2009      2  2009-02-01
17        Sep 2009  2009      9  2009-09-01
18        Oct 2010  2010     10  2010-10-01
19          6/2008  2008      6  2008-06-01
20         12/2009  2009     12  2009-12-01
21            2009  2009      1  2009-01-01
22            2010  2010      1  2010-01-01

TypeError:无法在类似字节的对象上使用字符串模式。

此错误表明列的类型为bytes,而不是str

此示例代码将引发相同的异常

re.findall('hello',b'hello kitty')

字节必须与字节进行模式匹配,或者先解码为str,然后再与字符串模式进行模式匹配,因此, fix 上面一行的两种方法是用b'hello'或将源字符串解码为某种形式(例如b'hello kitty'.decode('ascii') # 'utf8' would also work)。

要将字节列解码为str,可以使用str访问器并使用如上所示的`decode方法

示例

df5.str.decode('utf8') 

但是,我不确定您的正则表达式是否可以正常工作,但是由于我相信可以用更少的复杂性来实现您的目标,因此我没有尝试修复该问题。