You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Seaborn pairplot实现悬停标注与多轴点高亮?

基于Matplotlib/Seaborn原生实现Pairplot多轴点悬停标注与高亮

核心思路

利用Matplotlib鼠标事件监听机制,结合Seaborn Pairplot返回的轴对象与散点集合,通过以下步骤实现需求:

  • 遍历Pairplot所有子图,记录每个子图的散点艺术家
  • 监听鼠标移动事件,定位悬停点对应的DataFrame索引
  • 同步更新所有子图中对应索引点的透明度实现高亮
  • 显示对应索引的标注文本

完整代码示例

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

# 生成MCVE数据(以iris为例,添加聚类标签和自定义索引)
df = sns.load_dataset("iris")
df["cluster"] = np.random.randint(0, 3, size=len(df))
df.index = [f"sample_{i}" for i in range(len(df))]

# 创建带聚类标签的pairplot
g = sns.pairplot(df, hue="cluster", palette="tab10")

# 收集所有子图的散点艺术家
scatter_artists = []
for ax in g.axes.flat:
    # 遍历子图内元素,筛选散点对象
    for artist in ax.get_children():
        if isinstance(artist, plt.PathCollection):
            scatter_artists.append((ax, artist))

# 创建全局标注对象,初始隐藏
annot = g.fig.annotate(
    "", xy=(0,0), xytext=(20,20), textcoords="offset points",
    bbox=dict(boxstyle="round", fc="w"),
    arrowprops=dict(arrowstyle="->")
)
annot.set_visible(False)

# 存储原始透明度,用于后续恢复
original_alphas = []
for _, artist in scatter_artists:
    original_alphas.append(artist.get_alpha() or 1.0)

def hover(event):
    vis = annot.get_visible()
    # 鼠标不在轴内时,恢复所有点状态并隐藏标注
    if event.inaxes is None:
        for (_, artist), alpha in zip(scatter_artists, original_alphas):
            artist.set_alpha(alpha)
        annot.set_visible(False)
        g.fig.canvas.draw_idle()
        return
    
    # 定位当前轴对应的散点对象
    current_ax = event.inaxes
    current_scatter = None
    for ax, artist in scatter_artists:
        if ax == current_ax:
            current_scatter = artist
            break
    if current_scatter is None:
        return
    
    # 计算鼠标到每个点的距离,找到最近点索引
    points = current_scatter.get_offsets()
    dists = np.linalg.norm(points - np.array([event.xdata, event.ydata]), axis=1)
    min_dist_idx = np.argmin(dists)
    # 设置距离阈值,避免误触发
    if dists[min_dist_idx] > 10:
        for (_, artist), alpha in zip(scatter_artists, original_alphas):
            artist.set_alpha(alpha)
        annot.set_visible(False)
        g.fig.canvas.draw_idle()
        return
    
    # 高亮对应索引的点:全局点设低透明度,目标点恢复原透明度
    target_idx = min_dist_idx
    for (_, artist), alpha in zip(scatter_artists, original_alphas):
        alphas = np.full(len(points), 0.1)
        alphas[target_idx] = alpha
        artist.set_alpha(None)
        artist.set_facecolor(artist.get_facecolor())
        artist.get_facecolor()[:, 3] = alphas
    
    # 更新标注内容与位置
    annot.xy = points[target_idx]
    annot.set_text(df.index[target_idx])
    annot.set_visible(True)
    g.fig.canvas.draw_idle()

# 绑定鼠标移动事件
g.fig.canvas.mpl_connect("motion_notify_event", hover)

plt.show()

关键细节说明

  • 散点对象收集:Pairplot每个子图会因hue分组生成多个PathCollection,需遍历子图元素筛选所有散点对象
  • 索引匹配逻辑:Seaborn散点的点顺序与原始DataFrame行顺序完全一致,可直接通过索引关联跨子图的同一样本点
  • 高亮实现方式:通过修改散点颜色的alpha通道实现高亮,避免重新绘制点带来的性能损耗
  • 误触发规避:设置距离判断阈值,防止鼠标离点过远时触发无效高亮

内容的提问来源于stack exchange,提问作者Daniel F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 08:30:18