使用熊猫替换正则表达式以重新格式化字符串中的日期

时间:2019-04-18 17:08:38

标签: python regex pandas dataframe

我有一列类似下面的字符串,其中包含日期信息,并且我需要在前几位的月和日中添加前导零。我遇到了一些问题,试图仅使用pandas.DataFrame.replace和正则表达式来做到这一点。

import pandas as pd
df = pd.DataFrame({'Key':['0123456789_1/2/2019','0123456789_11/23/2019','0145892367_10/2/2019','0145892367_4/13/2019']})

df
Out[323]: 
                     Key
0    0123456789_1/2/2019
1  0123456789_11/23/2019
2   0145892367_10/2/2019
3   0145892367_4/13/2019

对于上面的列,重新格式化后我想要的输出将是:

                     Key
0  0123456789_01/02/2019
1  0123456789_11/23/2019
2  0145892367_10/02/2019
3  0145892367_04/13/2019

现在我已经知道我可以通过分割字符串来做到这一点:

r = df['Key'].str.split('_|/', expand=True)
df2 = r[0] + '_' + r[1].str.zfill(2) + '/' + r[2].str.zfill(2) + '/' + r[3]

df2
Out[333]: 
0    0123456789_01/02/2019
1    0123456789_11/23/2019
2    0145892367_10/02/2019
3    0145892367_04/13/2019
dtype: object

...但是当我最初尝试使用pandas.DataFrame.replace进行此操作时,我能够获得的最接近的是:

df2 = df.replace(r'(_|/)([1-9]/)',r'\1 0\2',regex=True)

df2
Out[335]: 
                      Key
0   0123456789_ 01/2/2019
1   0123456789_11/23/2019
2  0145892367_10/ 02/2019
3  0145892367_ 04/13/2019

我想进一步了解两个问题:

  1. 在类似行0的情况下,月份和日期都是个位数,则只能找到月份。我如何才能使它们匹配?
  2. 我不想要空格,但是当我尝试使用r'\10\2'进行替换时,我当然会收到错误消息,因为它认为我正在尝试替换第10组,并且在该组中没有这样的组第一个正则表达式。如果我尝试r'(\1)0\2',它会工作,除了它会打印文字括号。为什么要这样做,以及如何正确编写它,以便它立即打印第1组并紧随其后的是零?

为澄清起见进行编辑: 我知道我也可以通过解析日期来解决它,但是作为学习练习,我对正则表达式解决方案特别感兴趣。同样是因为单个replace对于大型数据帧而言要快得多。

2 个答案:

答案 0 :(得分:3)

IIUC,您可以使用:

df.Key=df.Key.str.split("_").str[0]+"_"+pd.to_datetime(df.Key.str.split("_")
            .str[1]).dt.strftime('%m/%d/%Y')
print(df)

                     Key
0  0123456789_01/02/2019
1  0123456789_11/23/2019
2  0145892367_10/02/2019
3  0145892367_04/13/2019

答案 1 :(得分:1)

使用datetime模块

df['Key'] = df.Key.str.split('_').apply(lambda x: x[0]+'_'+datetime.strptime(x[1], "%m/%d/%Y").strftime("%m/%d/%Y"))

输出

                     Key
0  0123456789_01/02/2019
1  0123456789_11/23/2019
2  0145892367_10/02/2019
3  0145892367_04/13/2019