如何在按Item分组后的DataFrame中对不同type的行应用自定义字符串差异计算函数
解决分组内不同type字符串的字符差异计算问题
我来帮你一步步实现这个需求,咱们先理清楚思路:要在每个Item分组内,把type1和type2的字符串两两配对,然后用你定义的get_mismatch函数计算字符差异数。
步骤1:导入必要的库并构造DataFrame
首先得导入pandas和functools里的reduce(因为你的自定义函数用到了它),然后创建原始的DataFrame:
import pandas as pd from functools import reduce # 构造原始数据 d = {'Item':['x','y','z','x','z','x'], 'strings' : ['abcd', 'abs', 'abcs', 'adbc','aaaa','abc'], 'type' : ['type1','type1','type1','type2','type2','type1']} df = pd.DataFrame(d)
步骤2:定义字符差异计算函数
你已经给出了这个函数,直接用就行:
def get_mismatch(str1: str, str2: str): return reduce(lambda x, y: x + 1 if y[0] != y[1] else x, zip(str1, str2), 0)
步骤3:编写分组处理逻辑
我们需要写一个自定义函数,用来处理每个Item分组:
- 先把分组内的
type1和type2行分开 - 如果其中一类没有数据(比如Item 'y'只有type1),就返回空表跳过
- 对两类字符串做笛卡尔积合并,得到所有可能的配对
- 计算每对字符串的差异数,最后整理成预期的格式
代码如下:
def process_group(group): # 分离type1和type2的字符串,并重命名列 type1_strings = group[group['type'] == 'type1'][['strings']].rename(columns={'strings': 'String_1'}) type2_strings = group[group['type'] == 'type2'][['strings']].rename(columns={'strings': 'String_2'}) # 如果其中一类没有数据,直接返回空DataFrame if type1_strings.empty or type2_strings.empty: return pd.DataFrame(columns=['Item', '#mismatch', 'String_1', 'String_2']) # 生成所有type1和type2字符串的配对(笛卡尔积) paired_strings = type1_strings.merge(type2_strings, how='cross') # 添加当前分组的Item名称 paired_strings['Item'] = group['Item'].iloc[0] # 计算每对字符串的字符差异数 paired_strings['#mismatch'] = paired_strings.apply( lambda row: get_mismatch(row['String_1'], row['String_2']), axis=1 ) # 调整列顺序,匹配预期输出 return paired_strings[['Item', '#mismatch', 'String_1', 'String_2']]
步骤4:应用分组处理并获取结果
把上面的函数应用到每个Item分组,然后重置索引:
final_result = df.groupby('Item').apply(process_group).reset_index(drop=True) print(final_result)
运行后得到的结果正好是你预期的:
Item #mismatch String_1 String_2 0 x 3 abcd adbc 1 x 2 abc adbc 2 z 3 abcs aaaa
补充说明
- 用
merge(how='cross')是为了确保每个type1的字符串都和每个type2的字符串配对,比如Item 'x'有两个type1字符串,都会和唯一的type2字符串计算差异 - 对于没有type2数据的Item(比如'y'),因为我们判断了空表的情况,所以不会出现在最终结果里
内容的提问来源于stack exchange,提问作者giupardeb




