代码之家  ›  专栏  ›  技术社区  ›  Cam

熊猫提取两个捕获组获取全部

  •  0
  • Cam  · 技术社区  · 3 年前

    我只是不太明白这个正则表达式。有人能帮忙吗。

    从以下内容开始:

    s = pd.Series(['Up to £48,000 a year', '£50,000 - £60,000 a year', '£11.86 - £14.69 an hour'])
    
    0        Up to £48,000 a year
    1    £50,000 - £60,000 a year
    2     £11.86 - £14.69 an hour
    3                   no salary
    

    首次尝试(缺少48000)

    s = pd.Series(['Up to £48,000 a year', '£50,000 - £60,000 a year', '£11.86 - £14.69 an hour', 'no salary'])
    s.str.extract(r'(\d\d[.,]\d\d\d?).*(\d\d[.,]\d\d\d?)')
    
        0       1
    0   NaN     NaN
    1   50,000  60,000
    2   11.86   14.69
    3   NaN     NaN
    

    第二次尝试(第二列中全部丢失)

    s = pd.Series(['Up to £48,000 a year', '£50,000 - £60,000 a year', '£11.86 - £14.69 an hour', 'no salary'])
    s.str.extract(r'(\d\d[.,]\d\d\d?).*(\d\d[.,]\d\d\d?)?')
    
        0       1
    0   48,000  NaN
    1   50,000  NaN
    2   11.86   NaN
    3   NaN     NaN
    

    我该怎么得到这个?

        0       1
    0   48,000  NaN
    1   50,000  60,000
    2   11.86   14.69
    3   NaN     NaN
    
    2 回复  |  直到 3 年前
        1
  •  2
  •   ziying35    3 年前

    试试这个:

    s.str.findall(r'(?:£)(\d+[,.]\d+)').apply(pd.Series)
    >>>
        0       1
    0   48,000  NaN
    1   50,000  60,000
    2   11.86   14.69
    3   NaN     NaN
    
        2
  •  1
  •   Wiktor Stribiżew    3 年前

    您可以使用 replace split :

    s.str.replace(r'.*?\b(\d+(?:[.,]\d+)*)(?:.*?(\d+(?:[.,]\d+)*))?.*|.+', r'\1 \2', regex=True).str.split(expand=True)
    

    输出:

            0       1
    0  48,000    None
    1  50,000  60,000
    2   11.86   14.69
    3    None    None
    

    请参阅 regex demo 详细信息 :

    • .*?\b(\d+(?:[.,]\d+)*)(?:.*?(\d+(?:[.,]\d+)*))?.* -除了换行符之外的任何零个或多个字符尽可能少( .*? ),然后是单词边界( \b ),则第1组-一个或多个数字+零次或多次出现 . , 以及后面的一个或多个数字,然后可选地出现除换行字符之外的任何零个或更多字符( .*? )然后第2组-一个或多个数字+零次或多次出现 , 以及后面的一个或多个数字,然后是行的其余部分( .* )
    • | -或
    • .+ -除了换行符之外的任何一个或多个字符,尽可能多。使用 ^.*$ 相反,如果行可以是空的,并且您仍然需要生产 NaN s分为两列。
        3
  •  0
  •   Kermit    3 年前

    尝试 Series.str.extractall

    可以找到RegEx模式中指定的所有捕获组,并在使用后重新整形 unstack

    s.str.extractall(r'([.\d][.,\d]*)').unstack()
    
    match       0       1
    0      48,000     NaN
    1      50,000  60,000
    2       11.86   14.69
    

    您可以使用进行测试 regex101

        4
  •  0
  •   Thanos Natsikas    3 年前

    做这项特定工作的方法不是很优雅

    vals = s.values
    rgx = '[A-Za-z£-]' # instead of finding the digits, get rid of eerything else
    vals = list(map(lambda x: re.sub(rgx,'',x).strip(), vals))
    vals = list(map(lambda x: re.split(r'\s+',x),vals))
    vals = list(map(lambda x: x if len(x) == 2 else [x[0],np.NAN],vals))
    s = pd.DataFrame(vals)
    print(s)
    
            0       1
    0  48,000     NaN
    1  50,000  60,000
    2   11.86   14.69
    

    或者类似的东西:

    df = pd.DataFrame(s.values)
    rgx = '[A-Za-z£-]'
    df[0] = df[0].str.replace(rgx,'', regex = True)
    df = df[0].str.split(r'\s+',expand = True)
    df.pop(df.columns[-1])
    

    它们都不适合更一般的情况,但如果有效的话。。。