具有 seaborn 和多个数据框的 mplcursors

mplcursors with seaborn and multiple dataframes

我在绘制来自多个 pandas DataFrame(或来自单个 DataFrame 的多个子集)的数据时尝试使用 mplcursors。 我已经阅读了 and , as well as 的答案,这与第一个有些冗余。 我能够调整 documentation on Extracting data and labels from a DataFrame 的代码以将 seaborn 与 单个 DataFrame 一起使用,即以下工作正常:

from matplotlib import pyplot as plt
import mplcursors
from pandas import DataFrame
import seaborn as sns
sns.set()

df = DataFrame(
    [("Alice", 163, 54),
     ("Bob", 174, 67),
     ("Charlie", 177, 73),
     ("Diane", 168, 57)],
    columns=["name", "height", "weight"])

fig, ax = plt.subplots()
sns.scatterplot(data=df, x="height", y="weight", ax=ax)

mplcursors.cursor().connect("add", lambda sel: sel.annotation.set_text(df["name"][sel.index]))

第一个问题的答案代码,它适用于多个 DataFrame,但没有使用 seaborn,对我来说也很好用。但是,如果我尝试对其进行调整以使其与 seaborn 一起使用,则不会生成任何光标。这是我的代码:

from matplotlib import pyplot as plt
import mplcursors
from pandas import DataFrame
import seaborn as sns

df = DataFrame([("Alice", 163, 54), ("Bob", 174, 67), ("Charlie", 177, 73), ("Diane", 168, 57)], columns=["name", "height", "weight"])
df1 = DataFrame([("Alice1", 140, 50), ("Bob1", 179, 60), ("Charlie1", 120, 70), ("Diane1", 122, 60)], columns=["name", "height", "weight"])

fig, ax = plt.subplots(1, 1)
# scat = ax.scatter(df["height"], df["weight"])# from the original answer
# scat1 = ax.scatter(df1["height"], df1["weight"])# from the original answer
scat = sns.scatterplot(data=df, x="height", y="weight")# my version
scat1 = sns.scatterplot(data=df1, x="height", y="weight")# my version
scat.annotation_names = [f'{n}\nh: {h}' for n, h in zip(df["name"], df["height"])]
scat1.annotation_names = [f'{n}\nw: {w}' for n, w in zip(df1["name"], df1["weight"])]

cursor = mplcursors.cursor([scat, scat1], hover=True)
cursor.connect("add", lambda sel: sel.annotation.set_text(sel.artist.annotation_names[sel.target.index]))

我在 Jupyter 中使用 mplcursors 版本 0.5.1 和 seaborn 版本 0.11.2,后端为 %matplotlib notebook

Matplotlib 的 ax.scatter returns 它创建的图形元素。另一方面,Seaborn returns 创建绘图的 ax (子图)。 (许多 seaborn 函数创建了许多不同类型的图形元素)。

在这种情况下,第一次调用时,元素存储在 ax.collections[0] 中,第二次调用时,元素存储在 ax.collections[1] 中。将这些分配给 scatscat1 变量模仿 matplotlib 方法。

from matplotlib import pyplot as plt
import mplcursors
from pandas import DataFrame
import seaborn as sns

df = DataFrame([("Alice", 163, 54), ("Bob", 174, 67), ("Charlie", 177, 73), ("Diane", 168, 57)], columns=["name", "height", "weight"])
df1 = DataFrame([("Alice1", 140, 50), ("Bob1", 179, 60), ("Charlie1", 120, 70), ("Diane1", 122, 60)], columns=["name", "height", "weight"])

fig, ax = plt.subplots()
sns.scatterplot(data=df, x="height", y="weight", ax=ax)
sns.scatterplot(data=df1, x="height", y="weight", ax=ax)
scat = ax.collections[0]
scat1 = ax.collections[1]
scat.annotation_names = [f'{n}\nh: {h}' for n, h in zip(df["name"], df["height"])]
scat1.annotation_names = [f'{n}\nw: {w}' for n, w in zip(df1["name"], df1["weight"])]

cursor = mplcursors.cursor([scat, scat1], hover=True)
cursor.connect("add", lambda sel: sel.annotation.set_text(sel.artist.annotation_names[sel.target.index]))
plt.show()