Possible to make labels appear when hovering over a point in matplotlib?

后端 未结 9 1045
清酒与你
清酒与你 2020-11-22 00:52

I am using matplotlib to make scatter plots. Each point on the scatter plot is associated with a named object. I would like to be able to see the name of an object when I ho

相关标签:
9条回答
  • 2020-11-22 01:28

    If you use jupyter notebook, my solution is as simple as:

    %pylab
    import matplotlib.pyplot as plt
    import mplcursors
    plt.plot(...)
    mplcursors.cursor(hover=True)
    plt.show()
    

    YOu can get something like

    0 讨论(0)
  • 2020-11-22 01:32

    This solution works when hovering a line without the need to click it:

    import matplotlib.pyplot as plt
    
    # Need to create as global variable so our callback(on_plot_hover) can access
    fig = plt.figure()
    plot = fig.add_subplot(111)
    
    # create some curves
    for i in range(4):
        # Giving unique ids to each data member
        plot.plot(
            [i*1,i*2,i*3,i*4],
            gid=i)
    
    def on_plot_hover(event):
        # Iterating over each data member plotted
        for curve in plot.get_lines():
            # Searching which data member corresponds to current mouse position
            if curve.contains(event)[0]:
                print "over %s" % curve.get_gid()
    
    fig.canvas.mpl_connect('motion_notify_event', on_plot_hover)           
    plt.show()
    
    0 讨论(0)
  • 2020-11-22 01:32

    mplcursors worked for me. mplcursors provides clickable annotation for matplotlib. It is heavily inspired from mpldatacursor (https://github.com/joferkington/mpldatacursor), with a much simplified API

    import matplotlib.pyplot as plt
    import numpy as np
    import mplcursors
    
    data = np.outer(range(10), range(1, 5))
    
    fig, ax = plt.subplots()
    lines = ax.plot(data)
    ax.set_title("Click somewhere on a line.\nRight-click to deselect.\n"
                 "Annotations can be dragged.")
    
    mplcursors.cursor(lines) # or just mplcursors.cursor()
    
    plt.show()
    
    0 讨论(0)
  • 2020-11-22 01:34

    mpld3 solve it for me. EDIT (CODE ADDED):

    import matplotlib.pyplot as plt
    import numpy as np
    import mpld3
    
    fig, ax = plt.subplots(subplot_kw=dict(axisbg='#EEEEEE'))
    N = 100
    
    scatter = ax.scatter(np.random.normal(size=N),
                     np.random.normal(size=N),
                     c=np.random.random(size=N),
                     s=1000 * np.random.random(size=N),
                     alpha=0.3,
                     cmap=plt.cm.jet)
    ax.grid(color='white', linestyle='solid')
    
    ax.set_title("Scatter Plot (with tooltips!)", size=20)
    
    labels = ['point {0}'.format(i + 1) for i in range(N)]
    tooltip = mpld3.plugins.PointLabelTooltip(scatter, labels=labels)
    mpld3.plugins.connect(fig, tooltip)
    
    mpld3.show()
    

    You can check this example

    0 讨论(0)
  • 2020-11-22 01:35

    The other answers did not address my need for properly showing tooltips in a recent version of Jupyter inline matplotlib figure. This one works though:

    import matplotlib.pyplot as plt
    import numpy as np
    import mplcursors
    np.random.seed(42)
    
    fig, ax = plt.subplots()
    ax.scatter(*np.random.random((2, 26)))
    ax.set_title("Mouse over a point")
    crs = mplcursors.cursor(ax,hover=True)
    
    crs.connect("add", lambda sel: sel.annotation.set_text(
        'Point {},{}'.format(sel.target[0], sel.target[1])))
    plt.show()
    

    Leading to something like the following picture when going over a point with mouse:

    0 讨论(0)
  • 2020-11-22 01:37

    I have made a multi-line annotation system to add to: https://stackoverflow.com/a/47166787/10302020. for the most up to date version: https://github.com/AidenBurgess/MultiAnnotationLineGraph

    Simply change the data in the bottom section.

    import matplotlib.pyplot as plt
    
    
    def update_annot(ind, line, annot, ydata):
        x, y = line.get_data()
        annot.xy = (x[ind["ind"][0]], y[ind["ind"][0]])
        # Get x and y values, then format them to be displayed
        x_values = " ".join(list(map(str, ind["ind"])))
        y_values = " ".join(str(ydata[n]) for n in ind["ind"])
        text = "{}, {}".format(x_values, y_values)
        annot.set_text(text)
        annot.get_bbox_patch().set_alpha(0.4)
    
    
    def hover(event, line_info):
        line, annot, ydata = line_info
        vis = annot.get_visible()
        if event.inaxes == ax:
            # Draw annotations if cursor in right position
            cont, ind = line.contains(event)
            if cont:
                update_annot(ind, line, annot, ydata)
                annot.set_visible(True)
                fig.canvas.draw_idle()
            else:
                # Don't draw annotations
                if vis:
                    annot.set_visible(False)
                    fig.canvas.draw_idle()
    
    
    def plot_line(x, y):
        line, = plt.plot(x, y, marker="o")
        # Annotation style may be changed here
        annot = ax.annotate("", xy=(0, 0), xytext=(-20, 20), textcoords="offset points",
                            bbox=dict(boxstyle="round", fc="w"),
                            arrowprops=dict(arrowstyle="->"))
        annot.set_visible(False)
        line_info = [line, annot, y]
        fig.canvas.mpl_connect("motion_notify_event",
                               lambda event: hover(event, line_info))
    
    
    # Your data values to plot
    x1 = range(21)
    y1 = range(0, 21)
    x2 = range(21)
    y2 = range(0, 42, 2)
    # Plot line graphs
    fig, ax = plt.subplots()
    plot_line(x1, y1)
    plot_line(x2, y2)
    plt.show()
    
    0 讨论(0)
提交回复
热议问题