如何从扁平DataFrame计算交叉总和用于生成Seaborn热图
实现步骤
1. 预处理基础数据
首先修正示例中set_index未赋值的小问题,保留歌曲维度的明细结构:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt demo_df = pd.DataFrame([ ("Get Back", 1,0,2), ("Help", 5, 2, 0), ("Let It Be", 0,2,2) ],columns=["Song","John", "Paul", "Ringo"]) # 正确设置歌曲为行索引 item_df = demo_df.set_index("Song") # 提取所有人员列名作为交叉表的行/列表头 people_list = item_df.columns.tolist()
2. 计算两两人员的共有项总贡献
核心计算逻辑:逐行遍历每一首歌曲,识别出对该歌曲有非零贡献的人员,对这些人员的两两组合,把两人在该歌曲上的贡献值之和累加到对应的交叉格子中,最终生成对称矩阵:
# 初始化全零的对称结果矩阵 overlap_matrix = pd.DataFrame( np.zeros((len(people_list), len(people_list))), index=people_list, columns=people_list ) # 逐行计算每首歌对交叉格子的贡献 for _, row in item_df.iterrows(): # 筛选当前行中对该歌曲有非零贡献的人员 active_people = row[row > 0].index.tolist() # 遍历活跃人员的所有两两组合 for i in range(len(active_people)): for j in range(i+1, len(active_people)): p1, p2 = active_people[i], active_people[j] current_contribution = row[p1] + row[p2] # 对称矩阵两个方向的格子同步累加 overlap_matrix.loc[p1, p2] += current_contribution overlap_matrix.loc[p2, p1] += current_contribution # 将对角线(自身与自身的交叉位)设置为空值,匹配示例格式 np.fill_diagonal(overlap_matrix.values, np.nan)
计算完成后的矩阵和目标格式完全一致:
John Paul Ringo John NaN 7.0 3.0 Paul 7.0 NaN 4.0 Ringo 3.0 4.0 NaN
3. 用Seaborn绘制热图
直接把计算好的对称矩阵传入Seaborn热图接口,通过mask参数隐藏对角线的空值即可:
sns.heatmap( overlap_matrix, annot=True, fmt=".0f", cmap="Blues", mask=overlap_matrix.isna() ) plt.title("人员间共有项贡献值") plt.show()
常见卡点说明
之前尝试用groupby+unstack方案没跑通的核心原因:这类长表聚合逻辑天然缺少“判断两人是否同时在单条记录上有非零值”的前置筛选步骤,直接做交叉聚合会把单人贡献的数值也计入重叠值,导致结果和预期偏差。
内容的提问来源于stack exchange,提问作者Phil Sheard
相关产品推荐
相关产品推荐

