regex 通过正则表达式拆分列并在pandas中仅保留匹配项

o4tp2gmn  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(73)

我需要有一个列每我的正则匹配。
考虑下面的dataframe:

Letter      Actions
r1          a95,a20
r2          a30,a12-rf,a15,a75
r3          0
r4          a15,a74
r5          a11

我期望:

Letter      Action1      Action2      Action3      Action4
r1          a95          a20          
r2          a30          a12          a15          a75
r3          
r4          a15          a74
r5          a11

我有下面的,但它保留了所有其他的东西,而我只需要模式匹配:

import pandas as pd

df = pd.DataFrame(
    [['r1', 'a95,a20'],
     ['r2', 'a30,a12-rf,a15,a75'],
     ['r3', '0'],
     ['r4', 'a15,a74'],
     ['r5', 'a11']],
    columns=['Letter', 'Actions'])

Actions = df['Actions'].str.split(r'([a]\d{2})', expand=True)
icomxhvb

icomxhvb1#

下面是使用str.extractall()的选项

(df.set_index('Letter')['Actions']
.str.extractall(r'([a]\d{2})')[0]
.unstack()
.rename(lambda x: 'Action{}'.format(x+1),axis=1)
.reset_index()
.rename_axis(None,axis=1))

另一种可能性是使用str.split()

df.set_index('Letter')['Actions'].str.split(r'(?:\D+)?,',expand=True)

输出:

Letter Action1 Action2 Action3 Action4
0     r1     a95     a20     NaN     NaN
1     r2     a30     a12     a15     a75
2     r4     a15     a74     NaN     NaN
3     r5     a11     NaN     NaN     NaN
1hdlvixo

1hdlvixo2#

你用错了splithttps://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.split.html
像这样的东西可能是你想要做的,尽管你仍然会保留-rf部分:

split(',', expand=True)

     0       1     2     3
0  a95     a20  None  None
1  a30  a12-rf   a15   a75
2    0    None  None  None
3  a15     a74  None  None
4  a11    None  None  None

此外,你的正则表达式遇到了一些常见的初学者问题,所以在python中阅读正则表达式是一个好主意。https://docs.python.org/3/howto/regex.html。特别是你的[a]是没有意义的,因为它和普通的a是一样的。
如果你知道你可以分割的最大元素数,那么你可以使用正则表达式和extract,这也是你想要的。https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.extract.html
就像

extract(r'(a\d\d)(?:-[^,]+)?(?:,(a\d\d)(?:-[^,]+)?)?(?:,(a\d\d)(?:-[^,]+)?)?(?:,(a\d\d)(?:-[^,]+)?)?')

     0    1    2    3
0  a95  a20  NaN  NaN
1  a30  a12  a15  a75
2  NaN  NaN  NaN  NaN
3  a15  a74  NaN  NaN
4  a11  NaN  NaN  NaN

在匹配a12-rf并只保留a12部分方面,您需要像(a\d\d)(?:-[^,]+)?这样的正则表达式来捕获a12(a\d\d),然后匹配但不保留-rf,您使用非捕获组?:修饰符,然后将-rf-[^,]+匹配,其中[^,]+匹配1个或多个非,字符。
这就是我得到(a\d\d)(?:-[^,]+)?的方法。对于字符串中的其他parts元素,您可以将此模式 Package 在其自己的非捕获组中,以处理可选并添加逗号进行匹配。(?:,<prev_pattern>)? .然后根据需要多次复制粘贴,<pattern>匹配。
如果你不知道你可以命中多少个元素,那么你可以使用extractall,然后透视它使用的MultiIndex。这听起来很复杂(我不得不承认在我的脑海里做这件事有点痛苦),但在实践中相当简单。

extractall(r'(a\d\d)(?:-[^,]+)?').unstack()[0]

match    0    1    2    3
0      a95  a20  NaN  NaN
1      a30  a12  a15  a75
3      a15  a74  NaN  NaN
4      a11  NaN  NaN  NaN

相关问题