Python 如何在将鼠标悬停在数据上时显示数据标签

Python 如何在将鼠标悬停在数据上时显示数据标签,python,pandas,matplotlib,Python,Pandas,Matplotlib,我正在绘制一些数据,看起来像 931,Oxfordshire,9314125,123255,Larkmead School,Abingdon,125,124,20,SUPP,8 931,Oxfordshire,9314126,123256,John Mason School,Abingdon,164,164,25,6,16 931,Oxfordshire,9314127,123257,Fitzharrys School,Abingdon,150,149,9,0,11 931,Oxfordshir

我正在绘制一些数据,看起来像

931,Oxfordshire,9314125,123255,Larkmead School,Abingdon,125,124,20,SUPP,8
931,Oxfordshire,9314126,123256,John Mason School,Abingdon,164,164,25,6,16
931,Oxfordshire,9314127,123257,Fitzharrys School,Abingdon,150,149,9,0,11
931,Oxfordshire,9316076,123298,Our Lady's Abingdon,Abingdon,57,57,SUPP,SUPP,16
我的基本步骤是

df = pandas.read_csv("file.csv", names=['A','B','C','D','E','F','G', 'H','I','J', 'K'], header=None)
df.replace('SUPP', 3.0, inplace=True)
df = df.convert_objects(convert_numeric=True)
df['KG'] = df['K']*1.0/df['G']
plt.plot(result['KG'])
plt.show()

然而,当我把鼠标移到图表上时,我真的很想知道每个学校的名称,这样我就可以浏览数据了。有什么方法可以做到这一点吗?

为了插入我自己的项目,请查看
mpldatacursor

作为一个基本示例,只需调用
datacursor(hover=True,point_labels=df['E'])
就可以实现90%的目标。例如,以上面的代码片段为例:

from StringIO import StringIO
import pandas as pd
import matplotlib.pyplot as plt
from mpldatacursor import datacursor

f = StringIO(
"""931,Oxfordshire,9314125,123255,Larkmead School,Abingdon,125,124,20,SUPP,8
931,Oxfordshire,9314126,123256,John Mason School,Abingdon,164,164,25,6,16
931,Oxfordshire,9314127,123257,Fitzharrys School,Abingdon,150,149,9,0,11
931,Oxfordshire,9316076,123298,Our Lady's Abingdon,Abingdon,57,57,SUPP,SUPP,16
""")
df = pd.read_csv(f, names=['A','B','C','D','E','F','G', 'H','I','J', 'K'],
                 header=None)
df.replace('SUPP', 3.0, inplace=True)
df = df.convert_objects(convert_numeric=True)
df['KG'] = df['K']*1.0/df['G']
plt.plot(df['KG'], marker='o')

datacursor(hover=True, point_labels=df['E'])

plt.show()

当线路悬停在上方时,我们将得到一个弹出标签

但是,根据设计,默认行为是在将行悬停/单击时显示弹出窗口。因此,当使用
point_labels
选项时,结果可能与您的想法不完全一致:

如果您只希望在顶点悬停时显示弹出窗口,则可以使用类似的解决方案:(在下一版本中,将有一个选项仅显示顶点处的弹出窗口,因此将来不再需要此解决方案。)

此外,您可能只想显示有问题的学校,而不是x、y坐标等。要更改此设置,请使用自定义
格式化程序
函数:

datacursor(l, hover=True, point_labels=df['E'],
           formatter=lambda **kwargs: kwargs['point_label'][0])

最后,您可能需要一个带有更漂亮箭头和不同相对位置的白色框:

datacursor(l, hover=True, point_labels=df['E'], bbox=dict(fc='white'),
           formatter=lambda **kwargs: kwargs['point_label'][0], xytext=(0, 25),
           arrowprops=dict(arrowstyle='simple', fc='white', alpha=0.5))

对于最后一个示例,将所有内容合并到一个可运行的版本中:

from StringIO import StringIO
import pandas as pd
import matplotlib.pyplot as plt
from mpldatacursor import datacursor

f = StringIO(
"""931,Oxfordshire,9314125,123255,Larkmead School,Abingdon,125,124,20,SUPP,8
931,Oxfordshire,9314126,123256,John Mason School,Abingdon,164,164,25,6,16
931,Oxfordshire,9314127,123257,Fitzharrys School,Abingdon,150,149,9,0,11
931,Oxfordshire,9316076,123298,Our Lady's Abingdon,Abingdon,57,57,SUPP,SUPP,16
""")
df = pd.read_csv(f, names=['A','B','C','D','E','F','G', 'H','I','J', 'K'],
                 header=None)
df.replace('SUPP', 3.0, inplace=True)
df = df.convert_objects(convert_numeric=True)
df['KG'] = df['K']*1.0/df['G']
plt.plot(df['KG'], marker='o')

l, = plt.plot(df['KG'], marker='o', linestyle='', visible=False)
datacursor(l, hover=True, point_labels=df['E'], bbox=dict(fc='white'),
           formatter=lambda **kwargs: kwargs['point_label'][0], xytext=(0, 25))

plt.show()

看一看我自己的项目,看一看
mpldatacursor
。在您的情况下,您需要使用
hover=True
point\u标签
选项。看看这里的例子:如果有机会,我会根据你的例子发布一个更详细的例子。这是一个非常好的回答。今天晚些时候我将更深入地研究它。出于兴趣,是否有可能在某一天将您的项目包含在matplotlib中?@felix-简而言之,如果您希望为各个顶点指定不同的标签,则必须指定
点标签。绘制数据时,Matplotlib将对象转换为数组。根本无法判断原始数据是在数据帧中,而不是在列表或numpy数组中。(请记住,matplotlib比pandas早了十多年。matplotlib中的核心数据结构是numpy数组。)因此,您无法访问数据帧的索引。如果未指定
点标签
,则传递到
格式化程序
函数的kwarg为
None
,这会导致类型错误。@felix-Use
display='multiple'
。如果要重新定位框,可能还需要
draggable=True
。看看这个例子:谢谢!您的项目确实需要a)添加到matplotlib中,b)以某种方式保存交互式图像:)哦,如果您再次单击某个点时删除标签,效果会更好。
from StringIO import StringIO
import pandas as pd
import matplotlib.pyplot as plt
from mpldatacursor import datacursor

f = StringIO(
"""931,Oxfordshire,9314125,123255,Larkmead School,Abingdon,125,124,20,SUPP,8
931,Oxfordshire,9314126,123256,John Mason School,Abingdon,164,164,25,6,16
931,Oxfordshire,9314127,123257,Fitzharrys School,Abingdon,150,149,9,0,11
931,Oxfordshire,9316076,123298,Our Lady's Abingdon,Abingdon,57,57,SUPP,SUPP,16
""")
df = pd.read_csv(f, names=['A','B','C','D','E','F','G', 'H','I','J', 'K'],
                 header=None)
df.replace('SUPP', 3.0, inplace=True)
df = df.convert_objects(convert_numeric=True)
df['KG'] = df['K']*1.0/df['G']
plt.plot(df['KG'], marker='o')

l, = plt.plot(df['KG'], marker='o', linestyle='', visible=False)
datacursor(l, hover=True, point_labels=df['E'], bbox=dict(fc='white'),
           formatter=lambda **kwargs: kwargs['point_label'][0], xytext=(0, 25))

plt.show()