从单个列中的子字符串/regex匹配项创建多个新的dataframe列

2024-10-03 23:25:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个pandas数据框,其中包含一个名为“Misc”的catch all列,其中包含可选的字符序列。例如:

    Misc
    1. xxx=something;yyyblah=somethingelse;xyx=blah
    2. xyz=meh;yzxx=random;xyx=meh

我真的只对4-5个价值观/案例感兴趣;我想为这些实例创建新的列并将它们添加到我的数据框架中,如果它们不存在,“.”或NaN。 所以如果我对xxx感兴趣=;和xyx=。。。;我的代码将执行以下操作:

    Misc                                                xxx          xyx
    1. xxx=something;yyyblah=somethingelse;xyx=blah |  something  |  blah
    2. xyz=meh;yzxx=random;xyx=meh                  |  .          |  meh

Misc中的所有信息将以一组20-30个字符串开头,以“;”结尾。我试过使用正则表达式

    df['xxx'] = df.Misc.str.extract(r'*(xxx=)*;)$', expand=True)

但这似乎不起作用。我还考虑过简单地删除所有我不关心的实例,然后进行拆分以获得一致性。有什么想法吗


Tags: 数据实例dfrandomsomething感兴趣xxxmisc
3条回答

将捕获组更改为在xxx=之后匹配,而不是在xxx=本身之后匹配。(?:;|$)检查作为终止符的;或行尾

df['xxx'] = df.Misc.str.extract(r'xxx=(.*?)(?:;|$)', expand=True)
df['xyx'] = df.Misc.str.extract(r'xyx=(.*?)(?:;|$)', expand=True)

或者您可以^{}在理解中自动创建这些列:

keys = ['xxx', 'xyx']
df = df.assign(**{key: df.Misc.str.extract(rf'{key}=(.*?)(?:;|$)', expand=True) for key in keys})

输出:

#                                               Misc                     xxx   xyx
# 0  1. xxx=something;yyyblah=somethingelse;xyx=blah               something  blah
# 1                   2. xyz=meh;yzxx=random;xyx=meh                     NaN   meh
# 2                             3. xxx=foo;xxxxy=bar                     foo   NaN
# 3              4. xxx=meh,blah/other=super 3;zzz=1  meh,blah/other=super 3   NaN

计时

我无法得到Andrej的答案来处理我的问题(重新编制索引错误),但以下是包含40K行的其他计时:

>>> df = pd.DataFrame({'Misc':['1. xxx=something;yyyblah=somethingelse;xyx=blah','2. xyz=meh;yzxx=random;xyx=meh','3. xxx=foo;xxxxy=bar','4. xxx=meh,blah/other=super 3;zzz=1']})
>>> df = pd.concat([df]*10000)

>>> %timeit tdy(df)
75.5 ms ± 5.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

>>> %timeit wwnde(df)
83.6 ms ± 1.63 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

请尝试命名组

df.Misc.str.extract('(?P<xxx>(?<=^xxx\=)\w+)|(?P<xyx>(?<=xyx\=)\w+$)')

使用(?<=X)Y也称为正向查找断言。其中Y仅当X位于其左侧时才匹配。用str.extract链接这个

df[['xxx','xyx']]=df.Misc.str.extract('((?<=^xxx\=)\w+)'),df.Misc.str.extract('((?<=xyx\=)\w+$)')

任何一种解决方案都会导致

      Misc                                            xxx   xyx
0  xxx=something;yyyblah=somethingelse;xyx=blah  something  blah
1                   xyz=meh;yzxx=random;xyx=meh        NaN   meh

要展开所有参数,可以使用^{}

x = (
    df.Misc.str.extractall(r"([^=\s]+)=([^;]+);?")
    .groupby(level=0)[[0, 1]]
    .apply(lambda x: dict(zip(x[0], x[1])))
    .apply(pd.Series)
    .fillna("N/A")
)

df_out = pd.concat([df, x], axis=1)
print(df_out)

印刷品:

                                              Misc        xxx        yyyblah   xyx  xyz    yzxx
0  1. xxx=something;yyyblah=somethingelse;xyx=blah  something  somethingelse  blah  N/A     N/A
1                   2. xyz=meh;yzxx=random;xyx=meh        N/A            N/A   meh  meh  random

相关问题 更多 >