在 Pandas 中匹配混合字母和数字的组合

3
我是一个有用的助手,可以翻译文本。
我需要从Pandas df中提取子字符串,并将它们放入新列中。我的字符串看起来像:
hj_yu_fb824_as22
jk_yu_fb638

我需要提取:

 fb824
 fb638

此外,子字符串可以在数据帧的两个不同列中(即使只出现一次),因为数据帧看起来像这样:
col1                col2
mf_lp_gn817_ml46    d_nb_05340.gif 
desktop_300x250_mf  mf_lp_fb824_ml46.html 
desktop_300x250_mf  dd_lp_ig805.html 
desktop_728x90_mf   mf_lp_fb824_ml46.html 

我希望能获得类似以下的内容:
col1                col2                     col3
mf_lp_gn817_ml46    d_nb_05340.gif           gn817
desktop_300x250_mf  mf_lp_fb824_ml46.html    fb824
desktop_300x250_mf  dd_lp_ig805.html         ig805
desktop_728x90_mf   mf_lp_fb824_ml46.html    fb824

因此,子字符串看起来像:

1)开头是两个小写字母,后跟3个数字 2)在两个''之间或只有一个''之间,或者在'_'和'.'之间的其他字符之间

我想到了:

 \_([^()]*)\_

但是它只匹配在“_”之间的任何内容,而不考虑上述描述的模式。

此外,如何有效地将正则表达式应用于Pandas数据框?

以下是可重现的数据框:

df = DataFrame({'col1': {0: 'mf_lp_gn817_ml46',
 1: 'desktop_300x250_mf',
 2: 'desktop_300x250_mf',
 3: 'desktop_728x90_mf'},
 'col2': {0: 'd_nb_05340.gif ',
 1: 'mf_lp_fb824_ml46.html ',
 2: 'dd_lp_ig805.html ',
 3: 'mf_lp_fb824_ml46.html '},
 'col3': {0: 'gn817', 1: 'fb824', 2: 'ig805', 3: 'fb824'}})
2个回答

3

可能需要更多的输入字符串,但对于你上面的字符串,你可以使用以下正则表达式:

_([a-z]{2}[0-9]{3})[_.]
# this is an underscore
# followed by exactly 2 letters and 3 digits
# followed by an underscore or a dot
# the whole match is captured to group1

对于您上面的字符串,这将是:
mf_lp_gn817_ml46    d_nb_05340.gif           -> gn817
desktop_300x250_mf  mf_lp_fb824_ml46.html    -> fb824
desktop_300x250_mf  dd_lp_ig805.html         -> ig805
desktop_728x90_mf   mf_lp_fb824_ml46.html    -> fb824

请查看regex101.com上的演示

Python代码:

若要将其应用于您的DataFrame,请参见以下代码:

import pandas as pd
from pandas import DataFrame
import re

df = DataFrame({'col1': {0: 'mf_lp_gn817_ml46',
 1: 'desktop_300x250_mf',
 2: 'desktop_300x250_mf',
 3: 'desktop_728x90_mf'},
 'col2': {0: 'd_nb_05340.gif ',
 1: 'mf_lp_fb824_ml46.html ',
 2: 'dd_lp_ig805.html ',
 3: 'mf_lp_fb824_ml46.html '}})

regex = r'_([a-z]{2}[0-9]{3})[_.]'
for index, row in df.iterrows():
    for column in row.keys():
        m = re.search(regex, row[column])
        if m is not None:
            df.ix[index, 'col3'] = m.group(1)

这正是我所需要的!但是,如何将其应用于两列并仅在找到结果时在第三列中获取结果? - chopin_is_the_best
@xxxvinxxx:请查看已更新的答案,已在Jupyter Notebook中进行了测试。 - Jan

0

我从https://stackoverflow.com/users/1231450/jan的回答中学到了很多,非常优雅。我还发现了这个额外的步骤,并想做出贡献。

将生成的正则表达式对象保存以便重用更高效(如果你需要做很多次)。请参阅:https://docs.python.org/3.5/library/re.html 6.2.2.模块内容

prog = re.compile(r'_([a-z]{2}[0-9]{3})[_.]')

for index, row in df.iterrows():
    for column in row.keys():
        m = prog.search(row[column])
        if m is not None:
            df.ix[index, 'col3'] = m.group(1)

我仍然有点困惑,m.group(1)最终会失去开头和结尾的下划线。 - memebrain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接