Pandas 在圆内设置文本动画-Matplotlib
下面将基于给定半径设置圆和线的动画。我希望将情节与动画文本结合起来,突出显示圆圈内的不同部分。文本会为每个新帧更新,但不会删除以前的帧文本 注意:我试图保持动画功能,因为我希望轴保持不变,并且只为更新的数据设置动画Pandas 在圆内设置文本动画-Matplotlib,pandas,matplotlib,animation,Pandas,Matplotlib,Animation,下面将基于给定半径设置圆和线的动画。我希望将情节与动画文本结合起来,突出显示圆圈内的不同部分。文本会为每个新帧更新,但不会删除以前的帧文本 注意:我试图保持动画功能,因为我希望轴保持不变,并且只为更新的数据设置动画 import pandas as pd import matplotlib.pyplot as plt import numpy as np from matplotlib import animation import matplotlib.gridspec as gridspec
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation
import matplotlib.gridspec as gridspec
import math
df = pd.DataFrame({
'Time' : [1,1,1,1,2,2,2,2,3,3,3,3],
'X2' : [0,0,0,0,-1,-1,-1,-1,0,0,0,0],
'Y2' : [0,0,0,0,1,1,1,1,1,1,1,1],
'Angle' : [0,0,0,0,-45,-45,-45,-45,90,90,90,90],
})
fig = plt.figure(figsize = (8,10))
grid = gridspec.GridSpec(1, 2)
gridsize = (1, 2)
ax = plt.subplot2grid(gridsize, (0, 0))
ax2 = plt.subplot2grid(gridsize, (0, 1))
ax2.set_xlim(-10, 10)
ax2.set_ylim(-10, 10)
# the center of the compass
moving_x = np.array(df.groupby(['Time'])['X2'].apply(list))
moving_y = np.array(df.groupby(['Time'])['Y2'].apply(list))
moving_point = ax.scatter(moving_x[0], moving_y[0], c = 'black', marker = 'o', zorder = 3)
radius = df.drop_duplicates(subset = ['Time','X2', 'Y2'])[['X2', 'Y2']].values
circle = plt.Circle(radius[0], 10, color = 'black', fill = False, lw = 0.2)
circle2 = plt.Circle(radius[0], 10, color = 'red', fill = False, lw = 0.2)
ax.add_patch(circle)
ax2.add_patch(circle2)
line1, = ax.plot([],[], color = 'k', linewidth = 1)
line2, = ax.plot([],[], color = 'k', linewidth = 1)
t = df['Angle'][0]
angles = np.array(df.groupby(['Time'])['Angle'].apply(list))
angleText = df.drop_duplicates(subset = ['Time','Angle'])['Angle'].values
rot_mat = lambda theta:np.array([
[np.cos(np.deg2rad(theta)),-np.sin(np.deg2rad(theta))],
[np.sin(np.deg2rad(theta)),np.cos(np.deg2rad(theta))]
])
# compass tags
annotate_tags = ['N','E','S','W']
def animate(i) :
moving_point.set_offsets(np.c_[moving_x[0+i], moving_y[0+i]])
circle.center = (radius[i,0], radius[i,1])
xs1L1=-10.0/2**0.5
ys1L1=10.0/2**0.5
xs2L1=10.0/2**0.5
ys2L1=-10.0/2**0.5
xs1L2=-xs1L1
ys1L2=ys1L1
xs2L2=-xs1L2
ys2L2=ys2L1
cx=radius[i,0]
cy=radius[i,1]
theta=math.radians(angles[i][0])
x1L1=( (xs1L1+radius[i,0] - cx) * math.cos(theta) + (ys1L1+radius[i,1] - cy) * math.sin(theta) ) + cx
x2L1=( (xs2L1+radius[i,0] - cx) * math.cos(theta) + (ys2L1+radius[i,1]- cy) * math.sin(theta) ) + cx
y1L1=( -(xs1L1+radius[i,0] - cx) * math.sin(theta) + (ys1L1+radius[i,1] - cy) * math.cos(theta) ) + cy
y2L1=( -(xs2L1+radius[i,0] - cx) * math.sin(theta) + (ys2L1+radius[i,1] - cy) * math.cos(theta) ) + cy
line1.set_data([x1L1,x2L1],[y1L1,y2L1])
x1L2=( (xs1L2+radius[i,0] - cx) * math.cos(theta) + (ys1L2+radius[i,1] - cy) * math.sin(theta) ) + cx
x2L2=( (xs2L2+radius[i,0] - cx) * math.cos(theta) + (ys2L2+radius[i,1]- cy) * math.sin(theta) ) + cx
y1L2=( -(xs1L2+radius[i,0] - cx) * math.sin(theta) + (ys1L2+radius[i,1] - cy) * math.cos(theta) ) + cy
y2L2=( -(xs2L2+radius[i,0] - cx) * math.sin(theta) + (ys2L2+radius[i,1] - cy) * math.cos(theta) ) + cy
line2.set_data([x1L2,x2L2],[y1L2,y2L2])
# Animate compass tags for each frame
tag_pos = np.array([[0,8.5],[8.5,0],[0,-8.5],[-8.5,0]])
tag_pos = tag_pos @ rot_mat(angleText[i])
for tag,pos in zip(annotate_tags,tag_pos):
ax.annotate(tag,xy=pos+radius[i], xycoords='data',
fontsize=10,horizontalalignment='right', verticalalignment='bottom')
ani = animation.FuncAnimation(fig, animate, np.arange(0,3), blit = False)
您希望为
动画
功能之外的尽可能多的标记创建文本对象。在animate
函数set_text
和set_position
中,如下所示:
我建议您在动画功能之外使用
annotate
创建文本对象。然后,您可以在animate
函数中的那些文本对象上.set_x()
和.set_y()
,类似于对行使用.set_data()
的方式。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation
import matplotlib.gridspec as gridspec
import math
df = pd.DataFrame({
'Time' : [1,1,1,1,2,2,2,2,3,3,3,3],
'X2' : [0,0,0,0,-1,-1,-1,-1,0,0,0,0],
'Y2' : [0,0,0,0,1,1,1,1,1,1,1,1],
'Angle' : [0,0,0,0,-45,-45,-45,-45,90,90,90,90],
})
fig = plt.figure(figsize = (20,10))
grid = gridspec.GridSpec(1, 2)
gridsize = (1, 2)
ax = plt.subplot2grid(gridsize, (0, 0))
ax2 = plt.subplot2grid(gridsize, (0, 1))
ax2.set_xlim(-10, 10)
ax2.set_ylim(-10, 10)
# the center of the compass
moving_x = np.array(df.groupby(['Time'])['X2'].apply(list))
moving_y = np.array(df.groupby(['Time'])['Y2'].apply(list))
moving_point = ax.scatter(moving_x[0], moving_y[0], c = 'black', marker = 'o', zorder = 3)
radius = df.drop_duplicates(subset = ['Time','X2', 'Y2'])[['X2', 'Y2']].values
circle = plt.Circle(radius[0], 10, color = 'black', fill = False, lw = 0.2)
circle2 = plt.Circle(radius[0], 10, color = 'red', fill = False, lw = 0.2)
ax.add_patch(circle)
ax2.add_patch(circle2)
line1, = ax.plot([],[], color = 'k', linewidth = 1)
line2, = ax.plot([],[], color = 'k', linewidth = 1)
t = df['Angle'][0]
angles = np.array(df.groupby(['Time'])['Angle'].apply(list))
angleText = df.drop_duplicates(subset = ['Time','Angle'])['Angle'].values
rot_mat = lambda theta:np.array([
[np.cos(np.deg2rad(theta)),-np.sin(np.deg2rad(theta))],
[np.sin(np.deg2rad(theta)),np.cos(np.deg2rad(theta))]
])
# compass tags
annotate_tags = ['N','E','S','W']
annotation=[None]*len(annotate_tags)
for i in range(len(annotate_tags)):
annotation[i] = ax.annotate('', xy=(0, 0),xycoords='data',fontsize=10,horizontalalignment='right', verticalalignment='bottom')
def animate(i) :
moving_point.set_offsets(np.c_[moving_x[0+i], moving_y[0+i]])
circle.center = (radius[i,0], radius[i,1])
xs1L1=-10.0/2**0.5
ys1L1=10.0/2**0.5
xs2L1=10.0/2**0.5
ys2L1=-10.0/2**0.5
xs1L2=-xs1L1
ys1L2=ys1L1
xs2L2=-xs1L2
ys2L2=ys2L1
cx=radius[i,0]
cy=radius[i,1]
theta=math.radians(angles[i][0])
x1L1=( (xs1L1+radius[i,0] - cx) * math.cos(theta) + (ys1L1+radius[i,1] - cy) * math.sin(theta) ) + cx
x2L1=( (xs2L1+radius[i,0] - cx) * math.cos(theta) + (ys2L1+radius[i,1]- cy) * math.sin(theta) ) + cx
y1L1=( -(xs1L1+radius[i,0] - cx) * math.sin(theta) + (ys1L1+radius[i,1] - cy) * math.cos(theta) ) + cy
y2L1=( -(xs2L1+radius[i,0] - cx) * math.sin(theta) + (ys2L1+radius[i,1] - cy) * math.cos(theta) ) + cy
line1.set_data([x1L1,x2L1],[y1L1,y2L1])
x1L2=( (xs1L2+radius[i,0] - cx) * math.cos(theta) + (ys1L2+radius[i,1] - cy) * math.sin(theta) ) + cx
x2L2=( (xs2L2+radius[i,0] - cx) * math.cos(theta) + (ys2L2+radius[i,1]- cy) * math.sin(theta) ) + cx
y1L2=( -(xs1L2+radius[i,0] - cx) * math.sin(theta) + (ys1L2+radius[i,1] - cy) * math.cos(theta) ) + cy
y2L2=( -(xs2L2+radius[i,0] - cx) * math.sin(theta) + (ys2L2+radius[i,1] - cy) * math.cos(theta) ) + cy
line2.set_data([x1L2,x2L2],[y1L2,y2L2])
# Animate compass tags for each frame
tag_pos = np.array([[0,8.5],[8.5,0],[0,-8.5],[-8.5,0]])
tag_pos = tag_pos @ rot_mat(angleText[i])
k=0
for tag,pos in zip(annotate_tags,tag_pos):
annotation[k].set_text(tag)
annotation[k].set_position(xy=pos+radius[i])
k=k+1
ani = animation.FuncAnimation(fig, animate, np.arange(0,3), blit = False)
ani.save('test.gif', writer='imagemagick', fps=5)
plt.show()