在Pandas DataFrame中筛选互配对、同时长且通话类型相反的行
筛选配对通话记录的高效方案
输入DataFrame
| A-Party | B-Party | Duration | Call Type |
|---|---|---|---|
| A | B | 2 | In |
| B | A | 2 | out |
| B | A | 3 | in |
| c | B | 10 | in |
| B | c | 10 | out |
期望输出
| A-Party | B-Party | Duration | Call Type |
|---|---|---|---|
| A | B | 2 | In |
| B | A | 2 | out |
| c | B | 10 | in |
| B | c | 10 | out |
需求说明
需要筛选满足以下全部条件的行:
- 两行的A-Party与B-Party互为配对(如(A,B)和(B,A))
- 两行的Duration值完全相同
- 两行的Call Type互为相反(即一行是"In"/"in",另一行是"out",需处理大小写差异)
高效解决方案
1. 统一Call Type的大小写
原数据里Call Type大小写混杂,先统一转成小写,避免大小写差异导致判断错误:
df['Call Type'] = df['Call Type'].str.lower()
2. 生成配对唯一标识
为了让(A,B)和(B,A)这种互配对的行归为一组,把每行的A-Party和B-Party按字典序排序后拼成元组,这样互配对的行会有相同的pair_id:
df['pair_id'] = df.apply(lambda x: tuple(sorted([x['A-Party'], x['B-Party']])), axis=1)
3. 分组筛选符合条件的行
按pair_id和Duration分组,只保留组内同时包含"in"和"out"两种Call Type的行——这就同时满足了互配对、时长相同、通话类型相反的要求:
# 筛选出同时包含in和out的组 valid_rows = df.groupby(['pair_id', 'Duration']).filter(lambda group: {'in', 'out'}.issubset(group['Call Type'])) # 删除辅助用的pair_id列 final_result = valid_rows.drop('pair_id', axis=1)
4. 恢复原始Call Type大小写(可选)
如果需要保留原始数据的大小写格式,可以提前备份再恢复:
# 先备份原始Call Type df['Original_Call_Type'] = df['Call Type'] # 统一转小写处理 df['Call Type'] = df['Call Type'].str.lower() # 筛选完成后恢复原始大小写 final_result['Call Type'] = final_result['Original_Call_Type'] final_result = final_result.drop('Original_Call_Type', axis=1)
该方案利用分组和集合判断,时间复杂度为O(n log n)(主要来自排序生成pair_id的步骤),在大数据量场景下依然高效。
内容的提问来源于stack exchange,提问作者Zulqarnain Sabir
相关产品推荐
相关产品推荐

