从一个3D的numpy数组创建一个3D图表

29

好的,我觉得应该有一种简单的方法使用matplotlib创建一个三维散点图。我有一个3D numpy数组(dset),其中0表示我不想要一个点,1表示我想要,基本上现在要绘制它,我必须通过三个for:循环来完成:

for i in range(30):
    for x in range(60):
        for y in range(60):
            if dset[i, x, y] == 1:
                ax.scatter(x, y, -i, zdir='z', c= 'red')

有什么建议可以更高效地完成这个任务吗?任何想法都将不胜感激。

2个回答

33
如果您有一个像这样的dset,并且您只想获取1值,您可以使用nonzero,它“返回一个元组数组,每个维度都包含该维度中非零元素的索引。”。
例如,我们可以创建一个简单的3D数组:
>>> import numpy
>>> numpy.random.seed(29)
>>> d = numpy.random.randint(0, 2, size=(3,3,3))
>>> d
array([[[1, 1, 0],
        [1, 0, 0],
        [0, 1, 1]],

       [[0, 1, 1],
        [1, 0, 0],
        [0, 1, 1]],

       [[1, 1, 0],
        [0, 1, 0],
        [0, 0, 1]]])

查找非零元素的位置:

>>> d.nonzero()
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2]), array([0, 0, 1, 2, 2, 0, 0, 1, 2, 2, 0, 0, 1, 2]), array([0, 1, 0, 1, 2, 1, 2, 0, 1, 2, 0, 1, 1, 2]))
>>> z,x,y = d.nonzero()

如果我们想要一个更复杂的切割,我们可以做一些像 (d > 3.4).nonzero() 这样的事情,因为 True 具有整数值1并且被视为非零。
最后,我们绘制:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, -z, zdir='z', c= 'red')
plt.savefig("demo.png")

给予

demo 3d image


很好。不过我有一个关于 (d > 3.4).nonzero() 部分的问题,这会返回 d 中值大于 3.4 的位置吗? - pter
@pter:完全正确。(d > 3.4)会返回一个布尔数组,与d具有相同的形状,并且在条目> 3.4处为True,其他地方为False - DSM
太棒了,我不知道这个(通常不需要3D图形...但如果需要的话,这将非常棒!)谢谢DSM。 - Joran Beasley
有没有办法在matplotlib中使用3D numpy数组绘制表面图。 - MSS
有没有办法在matplotlib中使用3D numpy数组绘制表面图? - undefined

1
如果你希望避免使用 nonzero 选项(例如,如果你有一个 3D 的 numpy 数组,其值应该是数据点的颜色值),你可以像你所做的那样,但通过使用 ndenumerate 来节省一些代码行。
你的示例可能会变成:
for index, x in np.ndenumerate(dset):
    if x == 1:
        ax.scatter(*index, c = 'red')

我想重点就是您不需要使用嵌套的for循环来遍历多维numpy数组。

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