为了实现MCVE,我构建了以下pairplot个:

from sklearn.datasets import make_blobs
import pandas as pd
from sklearn.cluster import HDBSCAN
import seaborn as sns
import numpy as np ; np.random.seed(0)

centers = 4
data, c = make_blobs(n_samples    = 20, 
                     centers      = centers, 
                     n_features   = 3,
                     cluster_std  = np.random.rand(centers) * 2.5,
                     random_state = 0)

df = pd.DataFrame(data)

alg = HDBSCAN()
alg.fit(df)
df['Label'] = alg.labels_.astype(str)

g = sns.pairplot(df, hue = 'Label')

Simple pairplot显示了一些异常值,其基础值为DataFrame df.

我想要的是功能,显示一个点上悬停df.index的注释,并以某种方式突出显示这一点在所有其他绘图.

我已经找到了用于底层matplotlib.pyplot对象的悬停注释方法in this question,但是那里的代码似乎不太适合像上面的pairplot那样扩展到多ax figure.

我用mplcursors做了这件事,它给了我标签(但只是通过包括一个额外的包)

def show_hover_panel(get_text_func=None):
    cursor = mplcursors.cursor(hover=2)    
    if get_text_func:
        cursor.connect(
                event = "add",
                func  = lambda sel: sel.annotation.set_text(get_text_func(sel.index)),
                       )  
    return cursor


def on_add(index):
    print(index)
    ix = df.index[index]
    #size = np.zeros(df.shape[0])
    #size[index] = 1
    #g.map_upper(sns.scatterplot, size = size)
    #g.map_lower(sns.scatterplot, size = size)
    return "{}".format(ix)

show_hover_panel(on_add)

代码中被注释掉的部分是我(非常)不成功地试图使它突出显示所有相关点.我把这个相当滑稽的输出留给读者作为练习.

This example显示了如何通过mplcursors链接高光,但要求每个点都是自己的艺术家,这与seaborn不兼容.

有没有更聪明的方法来做多轴高亮显示,最好是在matplotlibseaborn中原生地进行多轴突出显示和多轴注释?

推荐答案

使用Seborn 0.13.2(和0.12.2)和matplotlib 3.8.3进行测试.

mplcursors是非常多才多艺的.例如,光标可以连接到来自不同子图的元素.在配对图的情况下,我们需要存储在ax.collections[0]中的散点.如果没有NaN个值,点将保持与数据帧中相同的顺序.sel.index是散点集合的索引,可用于索引数据帧.此外,可以将额外突出显示的元素添加到sel.extras.这样,当 Select 新点时,它们将被自动删除.

请注意,mplcurors是一个非常轻量级的库,但是重现它的功能是一项巨大的工作.如果你不想导入它,你也可以把它唯一的python文件放到你的源目录中.

下面的代码从mpg数据集开始,go 掉了NaN值. colored颜色 的 Select 是为了清楚地看到不同次要情节中突出的点.

import matplotlib.pyplot as plt
import seaborn as sns
import mplcursors

def show_annotation(sel):
    row = mpg.iloc[sel.index]  # selected row from the dataframe
    sel.annotation.set_text(f"{row['name']} ({row.origin} {row.model_year})\nmpg: {row.mpg}  hp:{row.horsepower}")
    sel.annotation.get_bbox_patch().set(fc="lightsalmon", alpha=0.9)
    for ax in g.axes.flat:
        if len(ax.collections) > 0:
            sel.extras.append(
                ax.scatter(*ax.collections[0].get_offsets()[sel.index], ec='red', fc='none', lw=3, s=50))

mpg = sns.load_dataset('mpg').dropna()

g = sns.pairplot(mpg, vars=['mpg', 'horsepower', 'weight', 'model_year'], hue='origin', palette='pastel')

cursor = mplcursors.cursor([ax.collections[0] for ax in g.axes.flat if len(ax.collections) > 0], hover=True)
cursor.connect("add", show_annotation)
plt.show()

mplcursors with sns.pairgrid and highlighting in subplots

Python相关问答推荐

Class_weight参数不影响RandomForestClassifier不平衡数据集中的结果

仅从风格中获取 colored颜色 循环

Python会扔掉未使用的表情吗?

Pandas 第二小值有条件

线性模型PanelOLS和statmodels OLS之间的区别

如何使用Python将工作表从一个Excel工作簿复制粘贴到另一个工作簿?

PyQt5,如何使每个对象的 colored颜色 不同?'

如何在WSL2中更新Python到最新版本(3.12.2)?

pandas:排序多级列

当递归函数的返回值未绑定到变量时,非局部变量不更新:

如何在表中添加重复的列?

如何在Python中获取`Genericums`超级类型?

解决调用嵌入式函数的XSLT中表达式的语法移位/归约冲突

旋转多边形而不改变内部空间关系

python sklearn ValueError:使用序列设置数组元素

用SymPy在Python中求解指数函数

python的文件. truncate()意外地没有截断'

Pandas数据框上的滚动平均值,其中平均值的中心基于另一数据框的时间

使用xlsxWriter在EXCEL中为数据帧的各行上色

如何将验证器应用于PYDANC2中的EACHY_ITEM?