2017-01-11 124 views
1

我正在繪製星團中的位置,我的數據在x,y,z位置以及時間索引的數據框中。Matplotlib三維散佈動畫

我能夠產生一個三維散點圖,並試圖產生一個旋轉的情節 - 我一直有點成功,但掙扎着通過動畫API。

如果我的「update_graph」函數只是返回一個新的ax.scatter(),舊的將保持繪製,除非我重建整個圖形。這似乎效率低下。另外,我必須將間隔設置得相當高,否則我的動畫會「跳過」其他任何一幀,所以它說我的表現相當糟糕。最後,我不得不使用「blit = False」,因爲我無法獲得3d散點圖的迭代器。顯然,「graph.set_data()」不起作用,我可以使用「graph.set_3d_properties」,但它只允許我使用新的z座標。

因此,我已拼湊一個cluuge--(i的數據採用的是在 https://www.kaggle.com/mariopasquato/star-cluster-simulations 滾動到下)

另外我只繪製100個點(數據=數據[data.id < 100])

我的(工作)的代碼如下:

def update_graph(num): 
    ax = p3.Axes3D(fig) 
    ax.set_xlim3d([-5.0, 5.0]) 
    ax.set_xlabel('X') 
    ax.set_ylim3d([-5.0, 5.0]) 
    ax.set_ylabel('Y') 
    ax.set_zlim3d([-5.0, 5.0]) 
    ax.set_zlabel('Z') 
    title='3D Test, Time='+str(num*100) 
    ax.set_title(title) 
    sample=data0[data0['time']==num*100] 
    x=sample.x 
    y=sample.y 
    z=sample.z 
    graph=ax.scatter(x,y,z) 
    return(graph) 

fig = plt.figure() 
ax = p3.Axes3D(fig) 

# Setting the axes properties 
ax.set_xlim3d([-5.0, 5.0]) 
ax.set_xlabel('X') 
ax.set_ylim3d([-5.0, 5.0]) 
ax.set_ylabel('Y') 
ax.set_zlim3d([-5.0, 5.0]) 
ax.set_zlabel('Z') 
ax.set_title('3D Test') 
data=data0[data0['time']==0] 
x=data.x 
y=data.y 
z=data.z 
graph=ax.scatter(x,y,z) 

# Creating the Animation object 
line_ani = animation.FuncAnimation(fig, update_graph, 19, 
           interval=350, blit=False) 
plt.show() 

回答

6

散點圖在3D是mpl_toolkits.mplot3d.art3d.Path3DCollection對象。這提供了一個屬性_offsets3d,該屬性託管一個元組(x,y,z)並且可以用來更新散點的座標。因此,不必在動畫的每次迭代中創建整個繪圖,而只需更新其點。

以下是有關如何執行此操作的工作示例。

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


a = np.random.rand(2000, 3)*10 
t = np.array([np.ones(100)*i for i in range(20)]).flatten() 
df = pd.DataFrame({"time": t ,"x" : a[:,0], "y" : a[:,1], "z" : a[:,2]}) 

def update_graph(num): 
    data=df[df['time']==num] 
    graph._offsets3d = (data.x, data.y, data.z) 
    title.set_text('3D Test, time={}'.format(num)) 


fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
title = ax.set_title('3D Test') 

data=df[df['time']==0] 
graph = ax.scatter(data.x, data.y, data.z) 

ani = matplotlib.animation.FuncAnimation(fig, update_graph, 19, 
           interval=40, blit=False) 

plt.show() 

此解決方案不允許blitting。但是,根據使用情況,可能根本不需要使用散點圖;使用正常plot可能同樣可能,這允許blitting - 如下面的示例所示。

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


a = np.random.rand(2000, 3)*10 
t = np.array([np.ones(100)*i for i in range(20)]).flatten() 
df = pd.DataFrame({"time": t ,"x" : a[:,0], "y" : a[:,1], "z" : a[:,2]}) 

def update_graph(num): 
    data=df[df['time']==num] 
    graph.set_data (data.x, data.y) 
    graph.set_3d_properties(data.z) 
    title.set_text('3D Test, time={}'.format(num)) 
    return title, graph, 


fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
title = ax.set_title('3D Test') 

data=df[df['time']==0] 
graph, = ax.plot(data.x, data.y, data.z, linestyle="", marker="o") 

ani = matplotlib.animation.FuncAnimation(fig, update_graph, 19, 
           interval=40, blit=True) 

plt.show() 
+0

多數民衆贊成我所需要的 - 我知道重繪整個事情是不正確的,但它是我能工作的唯一事情。作爲一個「教導一個人去釣魚」的跟進,我搜索了matplot文檔,並且找不到_offsets3d的任何提及。我是否需要包含github和代碼本身以供將來參考? – RDS

+1

這是一個很好的觀點。上面的解決方案使用_offsets3d這是一個私有方法(如前面的_所示)。那些沒有記錄。只有通過查看[源代碼](https://github.com/matplotlib/matplotlib)或在線查找使用示例才能找到它們。如果文檔沒有提供解決方案,我經常發現查看源代碼會很有幫助。不要忘記,問一個像你這樣的具體問題也有助於找到像_offsets3d這樣的隱藏寶石。 ;-)但是,由於私有函數在版本之間也可能會發生變化,因此通常應避免使用它們。 – ImportanceOfBeingErnest

0

如果使用Jupyter筆記本記得用%matplotlib notebook不使用%matplotlib inline