首页 > 解决方案 > 从python中的文本中提取多个日期

问题描述

我有一个看起来像这样的 DataFrame

Unit ID   Shipping to:
90        With x
91        With y
92        With z
116       Shipped to x 01/04/16. / Shipped to y - 09/08/18.
233       Shipped to z 03/01/17
265       Shipped to x 03/01/17 returned shipped to x 02/05/17
280       Shipped to x 06/01/17  Shipped to y 03/05/17 Shipped to z 12/12/17

我希望能够提取所有出现的 x、y 或 z 以及它后面的日期(如果有的话)。我无法确认 z,y 或 z 会出现多少次,但我想要一个看起来像这样的最终结果:

 Unit ID  Occurrence 1  Occurrence 2  Occurrence 3 Shipping to:
    90    x                                        With x
    91    y                                        With y
    92    z                                        With z
    116   x 01/04/16    y 09/08/18                 Shipped to x 01/04/16. / Shipped to y - 09/08/18.
    233   z 03/01/17                               Shipped to z 03/01/17
    265   x 03/01/17                               Shipped to x 03/01/17 returned shipped to x 02/05/17
    280   x 06/01/17    y 03/05/17    z 12/12/17   Shipped to x 06/01/17  Shipped to y 03/05/17 Shipped to z 12/12/17

到目前为止,我只设法使用此方法提取出现在每一列中的第一个日期

date_col = []
for row in df['Shipping to:']:
    match = re.search('\d{2}/\d{2}/\d{2}',str(row),re.IGNORECASE)
    date_col.append(match)
df['dates'] = date_col

标签: pythonregex

解决方案


数据框本身有一个非常好的功能:

df['Shipping to:'].str.extractall(r'(\d{1,2}/\d{1,2}/\d{2})').unstack()

请注意,我将您的正则表达式更改为包含一个组(带有()),并且我也在匹配月份和日期的单个数字。

测试以下 DataFrame(我知道这是无稽之谈,但它只是一个测试):

df = pd.DataFrame([['1/22/33'], ['2/33/44  aaa 22/112/3 gook'], ['22/4/55'], [''], [None], ['aaa 22/5/66 aa 11/22/33']], columns=['Shipping to:'])

我得到这个输出:

match   0   1
0   1/22/33     NaN
1   2/33/44     NaN
2   22/4/55     NaN
5   22/5/66     11/22/33

要在开头包含 x/y/z,请将正则表达式更改为r'([xyz] \d{1,2}/\d{1,2}/\d{2})'. 最后,如果要将这些匹配项作为新列添加到原始数据框中,可以使用join. 然后代码变为:

df.join(df['Shipping to:'].str.extractall(r'([xyz] \d{1,2}/\d{1,2}/\d{2})')\
    .unstack()[0])

请注意,我在调用后得到第 0 列unstack- 这有效地删除了多索引的 1 级并防止join抱怨。现在只是因为我很高兴地玩这个,我添加了一些代码来修复列名,以便它们与您的示例匹配:

df.join(df['Shipping to:'].str.extractall(r'([xyz] \d{1,2}/\d{1,2}/\d{2})')\
    .unstack()[0]\
    .rename(columns=lambda x: "Occurence " + str(x)))

推荐阅读