【问题标题】:How to show data labels when you mouse over data鼠标悬停在数据上时如何显示数据标签
【发布时间】:2014-02-24 20:48:24
【问题描述】:

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

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

但是,当我将鼠标悬停在图表上时,我真的很想获得每所学校的名称,以便探索数据。有没有办法做到这一点?

【问题讨论】:

标签: python pandas matplotlib


【解决方案1】:

只是为了插入我自己的项目,看看mpldatacursorhttps://github.com/joferkington/mpldatacursor

作为一个基本示例,只需调用 datacursor(hover=True, point_labels=df['E']) 即可让您获得 90% 的目标。例如,以上面的代码 sn-p 为例:

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 选项时,结果可能与您想象的不太一样:

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

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'])

plt.show()

此外,您可能只想显示相关学校,而不是 x、y 坐标等。要更改此设置,请使用自定义 formatter 函数:

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

【讨论】:

  • 这是一个非常棒的回复。我将在今天晚些时候更深入地研究它。出于兴趣,是否有可能有一天将您的项目包含在 matplotlib 中?
  • @felix - 简而言之,如果您想为各个顶点使用不同的标签,则必须指定 point_labels。当您绘制数据时,Matplotlib 会将事物转换为数组。绝对没有办法告诉原始数据在数据框中,而不是在列表或 numpy 数组中。 (请记住,matplotlib 比 pandas 早了十多年。matplotlib 中的核心数据结构是 numpy 数组。)因此,您无法访问数据帧的索引。当point_labels未指定时,传入formatter函数的kwarg为None,导致TypeError。
  • @felix - 使用display='multiple'。如果您想重新定位这些框,您可能还需要draggable=True。看看这个例子:github.com/joferkington/mpldatacursor#draggable-boxes
  • 谢谢!您的项目确实需要 a) 添加到 matplotlib 和 b) 以某种方式保存交互式图像:)
  • 哦,如果再次单击某个点时它会删除标签会更好。
猜你喜欢
  • 2012-06-04
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多