大熊猫如何识别具有特定模式的字符串

时间:2019-03-04 17:18:44

标签: python regex python-3.x pandas

我有一个df

inv_id    
W/E FEB 8 2017
W/E JAN 24 2018
W/E MAR 11 18
W/E APR 09 17
2018 Q1
2011 Q2

inv_id的值都是字符串。值具有以下格式(strftime

%b %d %Y
%b %d %y
%b %d(non zero padded) %Y
%b %d(non zero padded) %y
%Y Q\d(regex decimal)

strftime中找不到一个非填充月份的指令。

我想知道如何定义模式并使用pandas来识别它们,也许是pandas.Series.str.contains?所以结果看起来像

inv_id              is_date   
W/E FEB 8 2017      True
W/E JAN 24 2018     True
W/E MAR 11 18       True
W/E APR 09 17       True
2018 Q1             True
2011 Q2             True

更新。设法处理第二种情况,

df['inv_id'].str.contains(pat=r'\b(19|20)\d{2} Q\d{1}\b', regex=True)

2 个答案:

答案 0 :(得分:2)

您可能会发疯,使用更新的regex模块并利用子例程。
在这里,我们首先可以想到简单的砖块,然后将它们以可能的格式(由我命名为format1format2,... formatn)粘在一起。
看到这段可爱的代码:

(?(DEFINE)
   (?<month>JAN|FEB|MAR|APR)
   (?<day>\b\d{1,2}\b)
   (?<year>\b[12]\d{3}\b)
   (?<year_short>\b[012]\d\b)
   (?<quarter>Q[1234])
   (?<ws>\s*)

   # here comes the fun part
   (?<format1>(?&month)(?&ws)(?&day)(?&ws)(?:(?&year)|(?&year_short)))
   (?<format2>(?&year)(?&ws)(?&quarter))

   # check for any existance
   (?<formats>(?&format1)|(?&format2))
)
^(?=.*?(?&formats))

还有a demo on regex101.com。这需要通过应用的功能进行检查:

def check_format(string):
    if re.search(pattern, string):
        return True
    return False

df['is_date'] = df['inv_id'].apply(check_format)


最后,您可能会遇到以下问题:

import pandas as pd, regex as re
d = {'inv_id': ['W/E FEB 8 2017', 'W/E JAN 24 2018', 'W/E MAR 11 18', 'W/E APR 09 17', '2018 Q1', '2011 Q2', 'somejunk', 'garbage in here']}
df = pd.DataFrame(d)

rx = re.compile(r'''the pattern from above''', re.VERBOSE)

def check_format(string):
    return True if rx.search(string) else False

df['is_date'] = df['inv_id'].apply(check_format)
print(df)

哪个会产生

            inv_id  is_date
0   W/E FEB 8 2017     True
1  W/E JAN 24 2018     True
2    W/E MAR 11 18     True
3    W/E APR 09 17     True
4          2018 Q1     True
5          2011 Q2     True
6         somejunk    False
7  garbage in here    False

答案 1 :(得分:1)

您只需要一个复杂的正则表达式即可。

df['is_date'] = df['inv_id'].str.contains('^W/E\s+[A-Z]{3}\s+\d{1,2}\s+\d{2,4}$|^\d{4}\s+Q[1-4]$')