Matplotlib: Annotating a 3D scatter plot

2019-01-03 02:31发布

I'm trying to generate a 3D scatter plot using Matplotlib. I would like to annotate individual points like the 2D case here: Matplotlib: How to put individual tags for a scatter plot.

I've tried to use this function and consulted the Matplotlib docoment but found it seems that the library does not support 3D annotation. Does anyone know how to do this?

Thanks!

7条回答
别忘想泡老子
2楼-- · 2019-01-03 03:08

This answer is based on previous answer by user315582. I did a few modifications to provide a solution without using global variables.

import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import proj3d

def main():
    fig = plt.figure()
    ax = fig.add_subplot(111, projection = '3d')
    points = np.array([(1,1,1), (2,2,2)])
    labels = ['billy', 'bobby']
    plotlabels = []
    xs, ys, zs = np.split(points, 3, axis=1)
    sc = ax.scatter(xs,ys,zs)

    for txt, x, y, z in zip(labels, xs, ys, zs):
        x2, y2, _ = proj3d.proj_transform(x,y,z, ax.get_proj())
        label = plt.annotate(
            txt, xy = (x2, y2), xytext = (-20, 20),
            textcoords = 'offset points', ha = 'right', va = 'bottom',
            bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
            arrowprops = dict(arrowstyle = '-', connectionstyle = 'arc3,rad=0'))
        plotlabels.append(label)
    fig.canvas.mpl_connect('motion_notify_event', lambda event: update_position(event,fig,ax,zip(plotlabels, xs, ys, zs)))
    plt.show()


def update_position(e,fig,ax,labels_and_points):
    for label, x, y, z in labels_and_points:
        x2, y2, _ = proj3d.proj_transform(x, y, z, ax.get_proj())
        label.xy = x2,y2
        label.update_positions(fig.canvas.renderer)
    fig.canvas.draw()



if __name__ == '__main__':
    main()
查看更多
登录 后发表回答