如何通过Pandas extractall捕获组实现多匹配行的groupby分组?
解决Pandas中一行匹配多个分组时的groupby问题
当使用str.extract()处理包含多个匹配项的文本时,只能捕获第一个匹配结果,导致同时包含多个分组关键词的行仅被归入一个分组。而str.extractall()虽能捕获所有匹配,但返回的是带MultiIndex的二维DataFrame,直接传入groupby()会触发ValueError。以下是两种可行的解决方案:
方案一:合并DataFrame后分组
通过将原数据与extractall()的结果合并,让每个匹配项对应原数据的一行,再进行分组:
import pandas as pd import re from io import StringIO DATA = StringIO(''' colA;colB;colC Foo;1;1 Bar;2;2 Foo,Bar;3;3 ''') df = pd.read_csv(DATA, sep=';') # 1. 提取所有匹配项并重置索引,保留原行号 matches = df['colA'].str.extractall('(Bar|Foo)', flags=re.IGNORECASE).reset_index() # 2. 合并原DataFrame与匹配结果 merged_df = df.merge(matches, left_index=True, right_on='level_0') # 3. 按匹配值分组 for group_name, group_data in merged_df.groupby(0): print(f"'{group_name}'") print(group_data[['colA', 'colB', 'colC']]) print()
输出结果:
'Bar' colA colB colC 1 Bar 2 2 2 Foo,Bar 3 3 'Foo' colA colB colC 0 Foo 1 1 2 Foo,Bar 3 3
方案二:通过索引筛选直接分组
无需合并DataFrame,直接利用extractall()结果的MultiIndex提取原数据行:
import pandas as pd import re from io import StringIO DATA = StringIO(''' colA;colB;colC Foo;1;1 Bar;2;2 Foo,Bar;3;3 ''') df = pd.read_csv(DATA, sep=';') # 提取所有匹配项 matches = df['colA'].str.extractall('(Bar|Foo)', flags=re.IGNORECASE) # 遍历每个唯一匹配值,筛选对应行并分组 for group_name in matches[0].unique(): # 获取匹配该值的所有原行索引 row_ids = matches[matches[0] == group_name].index.get_level_values('level_0') # 提取对应分组数据 group_data = df.loc[row_ids] print(f"'{group_name}'") print(group_data) print()
该方案输出与方案一完全一致,适合不需要保留匹配序号的场景。
关键说明
str.extractall()返回的DataFrame包含两级索引:level_0对应原数据的行索引,match对应同一行内的匹配序号。直接传入groupby()会因分组键是二维结构报错,因此需要通过重置索引或提取level_0来关联原数据,将分组键转换为一维结构。
内容的提问来源于stack exchange,提问作者PedroA
相关产品推荐
相关产品推荐

