web-dev-qa-db-ja.com

Matplotlib 3D散布アニメーション

私は星団の位置をグラフ化しています。私のデータは、x、y、zの位置と時間インデックスを持つデータフレームにあります。

3D散布図を作成でき、回転プロットを作成しようとしていましたが、ある程度は成功していますが、アニメーションAPIに苦労しています。

「update_graph」関数が新しいax.scatter()を返すだけの場合、グラフ全体を再構築しない限り、古いものはプロットされたままになります。それは非効率的です。また、間隔をかなり高く設定するか、アニメーションを1フレームおきに「スキップ」する必要があるため、パフォーマンスがかなり悪いと言えます。 3D散布図の反復子を取得できないため、最後に「blit = False」を使用する必要があります。どうやら「graph.set_data()」は機能せず、「graph.set_3d_properties」を使用できますが、これにより新しいz座標のみが許可されます。

だから私はクルージュをまとめました 私が使用したデータは---(https://www.kaggle.com/mariopasquato/star-cluster-simulations 下にスクロールします)

また、100ポイントのみをプロットしています(data = data [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()
10
RDS

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

このソリューションではブリットは許可されません。ただし、使用状況によっては、散布図を使用する必要がない場合もあります。 normal plotを使用することも同様に可能です。これにより、ブリットが可能になります-次の例に示すように。

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

Jupyter Notebookを使用している場合は、%matplotlib notebook使用しない%matplotlib inline

0
Kuifie