2

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


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

fig,ax=plt.subplots(1,1)

ax.scatter(df["height"], df["weight"])


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

上面的代码可以在悬停一个点时显示标签;我想在使用多个数据框和多个散点图时显示一个点的标签。当我使用多个数据框和多个散点图时,即使将鼠标悬停在属于其他数据框的其他点上,它也仅显示一个数据框的标签(以代码下方部分中提到的为准)。

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

尝试使用两个数据框的代码:

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


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)

ax.scatter(df["height"], df["weight"])
ax.scatter(df1["height"], df1["weight"])

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

plt.show()

谢谢你。

4

1 回答 1

1

PathCollection为返回的引入一个新属性ax.scatter,我们可以存储要显示的名称。

下面的代码创建一个属性annotation_names,然后可以由注释函数检索。

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

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"])
scat.annotation_names = [f'{n}\nh: {h}' for n, h in zip(df["name"], df["height"])]
scat1 = ax.scatter(df1["height"], df1["weight"])
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()

PS:这是尝试通过鼠标移动删除注释。测试鼠标是否在 x 或 y 方向上远离目标移动了 2 个以上的数据单元。在您的应用中,理想距离可能会有所不同。

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

annotation_xy = [0,0]

def remove_annotations(event):
    global annotation_xy
    if event.xdata is not None and (abs(annotation_xy[0] - event.xdata) > 2 or abs(annotation_xy[1] - event.ydata) > 2):
        for s in cursor.selections:
            cursor.remove_selection(s)

def set_annotation(sel):
    global annotation_xy
    sel.annotation.set_text(sel.artist.annotation_names[sel.target.index])
    annotation_xy = sel.target

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"])
scat.annotation_names = df["name"]
scat1 = ax.scatter(df1["height"], df1["weight"])
scat1.annotation_names = df1["name"]

cursor = mplcursors.cursor([scat, scat1], hover=True)
cursor.connect("add", set_annotation)
plt.connect('motion_notify_event', remove_annotations)

plt.show()
于 2020-07-23T10:05:49.990 回答