2

我对 python 和 matplotlib 很陌生,这个网站对我帮助很大。但我找不到关于这个主题的完整答案。

我想使用 matplotlib 注释 3d 图的点,所以经过一些研究后,我发现代码很平静: Matplotlib: Annotating a 3D scatter plot

    import pylab
    from mpl_toolkits.mplot3d import Axes3D
    from mpl_toolkits.mplot3d import proj3d
    fig = pylab.figure()
    ax = fig.add_subplot(111, projection = '3d')
    x = y = z = [1, 2, 3]
    sc = ax.scatter(x,y,z)
    # now try to get the display coordinates of the first point

    x2, y2, _ = proj3d.proj_transform(1,1,1, ax.get_proj())

    label = pylab.annotate(
        "this", 
        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'))

    def update_position(e):
        x2, y2, _ = proj3d.proj_transform(1,1,1, ax.get_proj())
        label.xy = x2,y2
        label.update_positions(fig.canvas.renderer)
        fig.canvas.draw()
    fig.canvas.mpl_connect('button_release_event', update_position)
    pylab.show()

但问题是,我设法用这段代码只更新最后一个标签,我试图在 update_position(e) 函数中做一些循环。但我肯定错过了一些东西。到目前为止,我使用了 Axes3D.text(x, y, z, s, zdir) 函数,但它看起来并不是很好。

谢谢 !

4

1 回答 1

3

我最近遇到了同样的问题,我的解决方案的灵感来自以下解决方案:

  1. Matplotlib:注释 3D 散点图
  2. 在 matplotlib 中用一个文本注释几个点

该解决方案基于创建一个“标签”数组,然后每个“标签”的位置在 update_position() 函数中更新。

import numpy
from mpl_toolkits.mplot3d import proj3d
import matplotlib.pyplot as plt
import pylab  

def update_position(e):
    print "From update position"
    #Transform co-ordinates to get new 2D projection
    tX, tY, _ = proj3d.proj_transform(dataX, dataY, dataZ, ax.get_proj())
    for i in range(len(dataX)):
        label = labels[i]
        label.xy = tX[i],tY[i]
        label.update_positions(fig.canvas.renderer)
    fig.canvas.draw()
    return

#Input 3D Data
data = numpy.array([[3,6,2],[4,6,2],[2,9,2],[3,6,10],[6,1,5]])

#Separate into X, Y, Z for greater clarity
dataX = data[:,0]
dataY = data[:,1]
dataZ = data[:,2]

plt.close()
fig = plt.figure()
ax = fig.gca(projection='3d')

#3D scatter plot
ax.scatter(dataX, dataY, dataZ, marker = 'o', c='b')

#Transform co-ordinates to get initial 2D projection
tX, tY, _ = proj3d.proj_transform(dataX, dataY, dataZ, ax.get_proj())

#Array of labels
labels = []

#Loop through data points to initially annotate scatter plot
#and populate labels array
for i in range(len(dataX)):
    text='['+str(int(dataX[i]))+','+str(int(dataY[i]))+','+str(int(dataZ[i]))+']'
    label = ax.annotate(text,
            xycoords='data',
            xy = (tX[i], tY[i]), xytext = (-20, 20),
            textcoords = 'offset points', ha = 'right', va = 'top', fontsize=6,
            bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
            arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
    labels.append(label)
#Positions are updated when mouse button is released after rotation.
fig.canvas.mpl_connect('button_release_event', update_position)
fig.show()
于 2013-10-10T10:32:27.287 回答