【问题标题】:Animating 3d scatterplot in matplotlib在 matplotlib 中动画 3d 散点图
【发布时间】:2012-07-07 18:43:08
【问题描述】:

我正在尝试根据here 发布的 2d 散点图动画和here 发布的 3d 线图,在 matplotlib 中获得散点图的 3d 动画。

问题来自set_data 和set_offsets 不能在 3D 中工作,因此您应该使用 set_3d_properties 来添加 z 信息。玩弄它通常会窒息,但它会运行下面发布的代码。但是,透明度增加得足以使点在几帧后消失。我在这里做错了什么?我希望这些点在框的范围内跳跃一段时间。即使将步长调整到非常小的值也不会降低透明度。

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

FLOOR = -10
CEILING = 10

class AnimatedScatter(object):
    def __init__(self, numpoints=5):
        self.numpoints = numpoints
        self.stream = self.data_stream()
        self.angle = 0

        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111,projection = '3d')
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
                                           init_func=self.setup_plot, blit=True)

    def change_angle(self):
        self.angle = (self.angle + 1)%360

    def setup_plot(self):
        x, y, z = next(self.stream)
        c = ['b', 'r', 'g', 'y', 'm']
        self.scat = self.ax.scatter(x, y, z,c=c, s=200, animated=True)

        self.ax.set_xlim3d(FLOOR, CEILING)
        self.ax.set_ylim3d(FLOOR, CEILING)
        self.ax.set_zlim3d(FLOOR, CEILING)

        return self.scat,

    def data_stream(self):
        data = np.zeros((3, self.numpoints))
        xyz = data[:3, :]
        while True:
            xyz += 2 * (np.random.random((3, self.numpoints)) - 0.5)
            yield data

    def update(self, i):
        data = next(self.stream)
        data = np.transpose(data)

        self.scat.set_offsets(data[:,:2])
        #self.scat.set_3d_properties(data)
        self.scat.set_3d_properties(data[:,2:],'z')

        self.change_angle()
        self.ax.view_init(30,self.angle)
        plt.draw()
        return self.scat,

    def show(self):
        plt.show()

if __name__ == '__main__':
    a = AnimatedScatter()
    a.show()

【问题讨论】:

  • 想通了,如果有人需要的话。删除所有关于 set_offsets 和 set_3d_properties 的行,然后使用这个:self.scat._offsets3d = (x,y,z),在这段代码中,显然是从数据中提取 x、y 和 z。
  • 是否可以将 plot() 与点一起使用而不是散点图?顺便说一句,您的解决方案对我有用。
  • @ericp 您应该发布您的解决方案作为答案...

标签: python matplotlib


【解决方案1】:

终于找到了解决办法,这里是如何在不接触颜色的情况下更新点:

from mpl_toolkits.mplot3d.art3d import juggle_axes
scat._offsets3d = juggle_axes(xs, ys, zs, 'z')

这是由 set_3d_properties 内部完成的以及重新初始化颜色

【讨论】:

    【解决方案2】:

    我找到了这个更通用的解决方案: 在将数据插入集合之前,您应该添加 np.ma.ravel( x_data ) ...。

    但是散点图似乎不是用于动画的;太慢了。

    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import numpy as np
    from mpl_toolkits.mplot3d import Axes3D
    
    FLOOR = -10
    CEILING = 10
    
    class AnimatedScatter(object):
        def __init__(self, numpoints=5):
            self.numpoints = numpoints
            self.stream = self.data_stream()
            self.angle = 0
    
            self.fig = plt.figure()
            self.ax = self.fig.add_subplot(111,projection = '3d')
            self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
                                               init_func=self.setup_plot, blit=True)
    
        def change_angle(self):
            self.angle = (self.angle + 1)%360
    
        def setup_plot(self):
            X = next(self.stream)
            c = ['b', 'r', 'g', 'y', 'm']
            self.scat = self.ax.scatter(X[:,0], X[:,1], X[:,2] , c=c, s=200, animated=True)
    
            self.ax.set_xlim3d(FLOOR, CEILING)
            self.ax.set_ylim3d(FLOOR, CEILING)
            self.ax.set_zlim3d(FLOOR, CEILING)
    
            return self.scat,
    
        def data_stream(self):
            data = np.zeros(( self.numpoints , 3 ))
            xyz = data[:,:3]
            while True:
                xyz += 2 * (np.random.random(( self.numpoints,3)) - 0.5)
                yield data
    
        def update(self, i):
            data = next(self.stream)
            data = np.transpose(data)
    
            self.scat._offsets3d = ( np.ma.ravel(data[:,0]) , np.ma.ravel(data[:,0]) , np.ma.ravel(data[:,0]) )
    
            self.change_angle()
            self.ax.view_init(30,self.angle)
            plt.draw()
            return self.scat,
    
        def show(self):
            plt.show()
    
    if __name__ == '__main__':
        a = AnimatedScatter()
        a.show()
    

    【讨论】:

      猜你喜欢
      • 2021-10-21
      • 2021-03-05
      • 2021-11-05
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 2015-10-18
      • 2012-05-09
      • 1970-01-01
      相关资源
      最近更新 更多