【问题标题】:Using mplcursors with more than one dataframe使用具有多个数据帧的 mplcursors
【发布时间】:2020-11-12 23:48:05
【问题描述】:

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()

谢谢。

【问题讨论】:

  • 让我知道如何通过使用 matplotlib 甚至处理悬停来获取具有多个散点图的图形以显示标签

标签: python pandas matplotlib hover mplcursors


【解决方案1】:

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

下面的代码创建了一个属性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()

【讨论】:

  • 因此,如果我有 N 个散点图,为了使其工作,我必须在上面示例中的 show_annotation(sel) 下的每个函数定义中显式删除 N-1 个选择?我至少有 10 个散点图。是否有一种仅使用 matplotlib 小部件在悬停时显示标签的有效方法?
  • 一切正常。移动光标后如何使标签消失。目前,标签一直存在,直到我移动到情节中的另一个点。
  • 在上面的例子中,'scat' 有没有办法显示名字和身高,而'scat1' 显示名字和体重?
  • 您可以存储annotation_names 列表中的任何内容。我更新了示例。
猜你喜欢
  • 1970-01-01
  • 2021-03-19
  • 2020-07-01
  • 2020-08-03
  • 2016-02-28
  • 1970-01-01
  • 2013-06-14
  • 2018-10-17
  • 1970-01-01
相关资源
最近更新 更多