本文介绍如何使用 pandas 高效统计每个用户在无序配对(如学生-评审员)中涉及的唯一联系人数量,自动将 (a,b) 和 (b,a) 视为同一关系,并汇总每人对应的去重联系人数。
在实际数据分析中,常遇到“对称关系”场景:例如师生互评、社交关注、协作配对等,其中 (student_login, reviewer_login) 与 (reviewer_login, student_login) 本质是同一组双向交互,不应重复计数。目标是为每个登录名(无论其角色)统计其唯一关联对象的数量——即该用户作为任一角色出现时,共与多少个不同用户组成过无序配对。
解决思路分为三步:
- 统一视角:将原始表中每行视为一条有向边(student → reviewer),再显式添加反向边(reviewer → student),使所有关系变为双向可访问;
- 标准化键名:将两列重命名为统一语义字段(如 ‘login’ 和 ‘unique_contacts’),便于后续聚合;
- 分组去重统计:按用户登录名分组,对其关联对象列调用 .nunique(),确保每个联系人仅计一次。
以下是完整实现代码:
import pandas as pd
# 构造示例数据
data = {
'student_login': ['login_1', 'login_2', 'login_1', 'login_2'],
'reviewer_login': ['login_2', 'login_1', 'login_3', 'login_3']
}
df = pd.DataFrame(data)
# 核心处理:合并正向 + 反向记录,并重命名列以统一语义
cols = ['login', 'unique_contacts']
forward = df.set_axis(cols, axis=1) # student→reviewer 映射为 login→unique_contacts
backward = df.set_axis(cols[::-1], axis=1) # reviewer→student 映射为 unique_contacts→login(再经groupby翻转)
combined = pd.concat([forward, backward], ignore_index=True)
result = combined.groupby('login', as_index=False)['unique_contacts'].nunique()
print(result)
输出: