在matplotlib中绘制3D散点图

13 投票
3 回答
18522 浏览
提问于 2025-04-16 14:45

我有一组Nx3的矩阵,使用scipy/numpy来处理。我想把这些数据做成一个三维散点图,其中X轴和Y轴的值分别来自矩阵的第一列和第二列,而每个柱子的高度则是第三列的值,柱子的数量由N决定。

每个矩阵代表一个不同的数据组,我希望每个数据组用不同的颜色来绘制,并且为整个图形设置一个图例。

我有以下的代码:

fig = pylab.figure()
s = plt.subplot(1, 1, 1)
colors = ['k', "#B3C95A", 'b', '#63B8FF', 'g', "#FF3300",
          'r', 'k']
ax = Axes3D(fig)
plots = []
index = 0

for data, curr_color in zip(datasets, colors):
    p = ax.scatter(log2(data[:, 0]), log2(data[:, 1]),
                   log2(data[:, 2]), c=curr_color, label=my_labels[index])

    s.legend()
    index += 1

    plots.append(p)

    ax.set_zlim3d([-1, 9])
    ax.set_ylim3d([-1, 9])
    ax.set_xlim3d([-1, 9])

问题是ax.scatter绘制的图形是透明的,我想去掉这种透明效果。另外,我还想设置x轴、y轴和z轴的刻度,该怎么做呢?

最后,虽然我在每次调用scatter的时候都设置了label="",但是图例并没有显示出来。我该如何让图例显示呢?

非常感谢你的帮助。

3 个回答

0

把参数 depthshade 设置为 False 就解决了我的问题:

ax.scatter(np.log2(data[:, 0]), np.log2(data[:, 1]), 
               np.log2(data[:, 2]), 'o', c=curr_color,  label=my_labels[index], depthshade=False)
4

据我所知,3D散点图的图例并没有直接支持。你可以查看这里的内容:http://matplotlib.sourceforge.net/users/legend_guide.html#plotting-guide-legend

不过,你可以用一种小技巧来解决这个问题,方法是使用一个叫“代理艺术家”的东西,像这样:

p = Rectangle((0, 0), 1, 1, fc="r")
axis.legend([p], ["Red Rectangle"])

这样,代理艺术家不会被添加到坐标轴上,但你可以用它来创建图例。

15

试试把 'ax.scatter' 换成 'ax.plot',可以加上 'o' 参数,这样就能得到类似的圆圈。这会解决透明度和图例的问题。

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

mpl.rcParams['legend.fontsize'] = 10

fig = plt.figure(1)
fig.clf()
ax = Axes3D(fig)
datasets = random((8,100,3))*512
my_labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

colors = ['k', "#B3C95A", 'b', '#63B8FF', 'g', "#FF3300",
          'r', 'k']
index = 0
for data, curr_color in zip(datasets, colors):
    ax.plot(np.log2(data[:, 0]), np.log2(data[:, 1]), 
                   np.log2(data[:, 2]), 'o', c=curr_color, label=my_labels[index])
    index += 1

ax.set_zlim3d([-1, 9])
ax.set_ylim3d([-1, 9])
ax.set_xlim3d([-1, 9])

ax.set_xticks(range(0,11))
ax.set_yticks([1,2,8])
ax.set_zticks(np.arange(0,9,.5))

ax.legend(loc = 'upper left')
    
plt.draw()

plt.show()

我加了一些代码和调整,来生成一些示例数据,让你的演示能正常运行。我相信你也能把它弄好的。

设置刻度需要2010年8月的 mplot3d 更新,具体可以在 这里 找到。我是从 Sourceforge 下载的最新 mplot3d。我不太确定 Matplotlib 1.0.1 是否包含这个最新的更新,因为我现在还在用 Python 2.6 和 Matplotlib 1.0.0。

编辑

这是一个快速简单的虚拟图,用来显示图例,同时保留从散点图得到的3D透明效果:

index = 0
for data, curr_color in zip(datasets, colors):
    ax.scatter(np.log2(data[:, 0]), np.log2(data[:, 1]), 
                   np.log2(data[:, 2]), 'o', c=curr_color, label=my_labels[index])
    ax.plot([], [], 'o', c = curr_color, label=my_labels[index])                    
    index += 1

撰写回答