【问题标题】:Match mixture of characters and digits in Pandas在 Pandas 中匹配字符和数字的混合
【发布时间】:2016-05-20 19:08:31
【问题描述】:

我需要从 pandas df 中提取子字符串,并将它们放入一个新列中。 我的字符串看起来像:

hj_yu_fb824_as22
jk_yu_fb638

我需要提取:

 fb824
 fb638

此外,它们的子字符串可以位于数据帧的两个单独列中(尽管只出现一次),因为 df 看起来像:

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'}})

【问题讨论】:

    标签: python regex pandas


    【解决方案1】:

    可能需要更多输入字符串,但对于上述字符串,您可以提出以下正则表达式:

    _([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
    

    a demo on 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)
    

    【讨论】:

    • 这正是我所需要的!但是,如何将其应用于两列并仅在找到第三列时才在第三列中获取结果?
    • @xxxvinxxx:查看更新后的答案,用 jupyter notebook 测试。
    【解决方案2】:

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

    保存生成的正则表达式对象以供重用更有效(如果您做的不止几个)。 见:https://docs.python.org/3.5/library/re.html6.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) 是如何在开头和结尾丢失下划线的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2018-03-15
    • 1970-01-01
    • 2017-02-05
    • 2017-08-31
    • 1970-01-01
    相关资源
    最近更新 更多