Tim
Tim

Reputation: 333

How to make mpld3 work with seaborn (interactive tooltips)

I can't seem to get the interactive tooltips powered by mpld3 to work with the fantastic lmplot-like scatter plots from seaborn.

I'd love any pointer on how to get this to work! Thanks!

Example Code:

# I'm running this in an ipython notebook.
%matplotlib inline
import matplotlib.pyplot as plt, mpld3
mpld3.enable_notebook()
import seaborn as sns


N=10
data = pd.DataFrame({"x": np.random.randn(N),
                     "y": np.random.randn(N), 
                     "size": np.random.randint(20,200, size=N),
                     "label": np.arange(N)
                     })


scatter_sns = sns.lmplot("x", "y", 
           scatter_kws={"s": data["size"]},
           robust=False, # slow if true
           data=data, size=8)
fig = plt.gcf()

tooltip = mpld3.plugins.PointLabelTooltip(fig, labels=list(data.label))
mpld3.plugins.connect(fig, tooltip)

mpld3.display(fig)

I'm getting the seaborn plot along with the following error:

Javascript error adding output!
TypeError: obj.elements is not a function
See your browser Javascript console for more details.

The console shows:

TypeError: obj.elements is not a function
    at mpld3_TooltipPlugin.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1161:9)
    at mpld3_Figure.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1400:23)
    at Object.mpld3.draw_figure (https://mpld3.github.io/js/mpld3.v0.2.js:18:9)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:14:14)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:15:5)
    at eval (native)
    at Function.x.extend.globalEval (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231)
    at x.fn.extend.domManip (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:21253)
    at x.fn.extend.append (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:18822)
    at OutputArea._safe_append (https://mbcomp1:9999/static/notebook/js/outputarea.js:336:26)
outputarea.js:319 Javascript error adding output! TypeError: obj.elements is not a function
    at mpld3_TooltipPlugin.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1161:9)
    at mpld3_Figure.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1400:23)
    at Object.mpld3.draw_figure (https://mpld3.github.io/js/mpld3.v0.2.js:18:9)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:14:14)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:15:5)
    at eval (native)
    at Function.x.extend.globalEval (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231)
    at x.fn.extend.domManip (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:21253)
    at x.fn.extend.append (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:18822)
    at OutputArea._safe_append (https://mbcomp1:9999/static/notebook/js/outputarea.js:336:26)
outputarea.js:338 TypeError: obj.elements is not a function
    at mpld3_TooltipPlugin.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1161:9)
    at mpld3_Figure.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1400:23)
    at Object.mpld3.draw_figure (https://mpld3.github.io/js/mpld3.v0.2.js:18:9)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:14:14)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:15:5)
    at eval (native)
    at Function.x.extend.globalEval (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231)
    at x.fn.extend.domManip (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:21253)
    at x.fn.extend.append (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:18822)
    at OutputArea._safe_append (https://mbcomp1:9999/static/notebook/js/outputarea.js:336:26)
outputarea.js:319 Javascript error adding output! TypeError: obj.elements is not a function
    at mpld3_TooltipPlugin.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1161:9)
    at mpld3_Figure.draw (https://mpld3.github.io/js/mpld3.v0.2.js:1400:23)
    at Object.mpld3.draw_figure (https://mpld3.github.io/js/mpld3.v0.2.js:18:9)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:14:14)
    at eval (eval at <anonymous> (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231), <anonymous>:15:5)
    at eval (native)
    at Function.x.extend.globalEval (https://mbcomp1:9999/static/components/jquery/jquery.min.js:4:4231)
    at x.fn.extend.domManip (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:21253)
    at x.fn.extend.append (https://mbcomp1:9999/static/components/jquery/jquery.min.js:5:18822)
    at OutputArea._safe_append (https://mbcomp1:9999/static/notebook/js/outputarea.js:336:26)

Upvotes: 2

Views: 6554

Answers (3)

Jeff M.
Jeff M.

Reputation: 1087

I was able to get the tooltips to work by using the standard matplotlib scatter on top of the seaborn plot and very low alpha (you can't use zero)

data_tip_points = ax.scatter(x_points, y_points, alpha=0.001)
tooltip = plugins.PointLabelTooltip(data_tip_points, labels)

It's a bit of a hack, but it works as seen here.

http://nbviewer.ipython.org/urls/bitbucket.org/jeff_mcgehee/cds_presentation_intro/raw/49cc7808ec26adebec94ffa83973bb5db13017d7/CDS%20Intro%20Presentation.ipynb

Upvotes: 2

Abraham D Flaxman
Abraham D Flaxman

Reputation: 2979

I don't think that there is an easy way to do this currently. I can get some of the tooltips to show by replacing your tooltip constructor with the following:

ax = plt.gca()
pts = ax.get_children()[3]
tooltip = mpld3.plugins.PointLabelTooltip(pts, labels=list(data.label))

This only works for the points outside of the uncertainty interval, though. I think it would be possible to extend seaborn to make these points highest in the zorder and store them in in the instance somewhere so that you don't need do pull them out of the axis children list. Perhaps worth a feature request.

Upvotes: 3

Ed Smith
Ed Smith

Reputation: 13206

Your code works for me on ipython (no notepad) when saving the figure to file with mpld3.save_html(fig,"./out.html"). May be an issue with ipython notepad/mpld3 compatibility or mpld3.display (which causes an error for me, although I think this is related to an old version of matplotlib on my computer).

The full code which worked for me is,

import numpy as np
import matplotlib.pyplot as plt, mpld3
import seaborn as sns
import pandas as pd

N=10
data = pd.DataFrame({"x": np.random.randn(N),
                     "y": np.random.randn(N), 
                     "size": np.random.randint(20,200, size=N),
                     "label": np.arange(N)
                     })


scatter_sns = sns.lmplot("x", "y", 
           scatter_kws={"s": data["size"]},
           robust=False, # slow if true
           data=data, size=8)
fig = plt.gcf()

tooltip = mpld3.plugins.PointLabelTooltip(fig, labels=list(data.label))
mpld3.plugins.connect(fig, tooltip)

mpld3.save_html(fig,"./out.html")

Upvotes: 0

Related Questions