在Matplotlib中绘制3D散点图

13

我有一组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函数会给绘制的图形添加透明度,我想要去掉它。此外,我还想设置xticks、yticks和zticks,你能告诉我如何做吗?
最后,尽管我为每个scatter调用都添加了label="",但legend没有出现。请问如何让图例显示出来?
非常感谢您的帮助。
3个回答

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()

我添加了一些代码并进行了一些调整,以获取一些样本数据并让你的演示其余部分正常工作。我认为你可以让它正常工作。

根据这里所述,设置刻度需要 August 2010 版的 mplot3d 更新。我从Sourceforge获取了最新的 mplot3d。由于我仍在运行 Python 2.6 和 Matplotlib 1.0.0,我不太确定 Matplotlib 1.0.1 是否包含此最新更新。

编辑

一个快速而简单的虚拟图表,用于实现散点图的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

绘图似乎比散点图表现更好。您还可以通过显式传递ax.plot(....,ls ='None')来禁用连接数据点的线条。 - mkocubinski
这几乎是完美的,谢谢!有一个问题:我意识到透明度是实现3D效果所必需的。如何做到与Scatter3D相同的效果,并且使它透明(用plot()函数)? - user248237
我认为你做不到。散点图的透明度取决于轴的方向,因此当你旋转时,透明度会改变。似乎在 plot 中你无法得到这个效果,因为它只是一个带有一点调整的二维图形;而 scatter 给你一个实际的三维补丁集合。如果你需要带有花哨的三维效果的透明度,则使用 scatter,并通过一些虚拟图形获得图例。或者,修复 scatter 代码,使其与图例一起工作;-) - Daan
请参见我的答案编辑,其中包含带有散布图的虚拟情节,以实现3D透明效果。 - Daan

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"])

因此,代理艺术家不会被添加到轴上,但您可以使用它来创建图例。

0

将 kwarg depthshade=False 设置为 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接