python - 将多个子图绘制为动画
问题描述
我有两个独立subplots
的,我希望显示为动画。对于下面的子图,ax1
显示动画scatter
图,而ax2
现在是散点图,我希望将其更改为line
plot
.
请注意:我已将问题简化为仅显示相关信息。但是我希望保持代码与现在相似。
以下是我的尝试:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import pandas as pd
DATA_LIMITS = [0, 15]
def datalimits(*data):
return DATA_LIMITS
fig = plt.figure(figsize=(10,18))
grid = plt.GridSpec(1, 3, wspace=0.4, hspace=0.3)
gridsize = (3, 2)
ax1 = plt.subplot2grid(gridsize, (0, 0), colspan=2, rowspan=2)
ax2 = plt.subplot2grid(gridsize, (2, 0), colspan=2, rowspan=2)
ax1.grid(False)
ax2.grid(False)
ax1.set_xlim(DATA_LIMITS)
ax1.set_ylim(DATA_LIMITS)
line_a, = ax1.plot([], [], 'o', c='red', alpha = 0.5, markersize=5,zorder=3)
line_b, = ax1.plot([], [], 'o', c='blue', alpha = 0.5, markersize=5,zorder=3)
lines=[line_a,line_b]
scat = ax1.scatter([], [], s=20, marker='o', c='white', alpha = 1,zorder=3)
scats=[scat]
line_d = ax2.plot([], [], 'o', c = 'k')
ax2.set_ylim(-6,6)
ax2.set_xlim(0,15)
def plots(tdf, xlim=None, ylim=None, fig=fig, ax=ax1):
df = tdf[1]
if xlim is None: xlim = datalimits(df['X'])
if ylim is None: ylim = datalimits(df['Y'])
for (group, gdf), group_line in zip(df.groupby('group'), lines+scats+line_d):
if group in ['A','B','D']:
group_line.set_data(*gdf[['X','Y']].values.T)
elif group in ['C']:
gdf['X'].values, gdf['Y'].values
scat.set_offsets(gdf[['X','Y']].values)
return [scat] + [line_a,line_b] + [line_d]
n = 9
time = range(n)
d = ({
'A1_X' : [13,14,12,13,11,12,13,12,11,10],
'A1_Y' : [6,6,7,7,7,8,8,8,9,10],
'A2_X' : [7,6,5,7,6,3,4,5,6,6],
'A2_Y' : [11,12,11,10,11,12,10,11,10,9],
'B1_X' : [8,9,8,7,6,7,5,6,7,6],
'B1_Y' : [3,4,3,2,3,4,2,1,2,3],
'B2_X' : [13,14,14,14,13,13,13,12,12,12],
'B2_Y' : [5,4,3,2,4,5,4,6,3,3],
'C1_X' : [5,6,7,5,6,5,6,5,6,5],
'C1_Y' : [10,11,10,11,12,11,10,8,7,6],
'D1_X' : [0,1,2,3,4,5,6,7,8,9],
'D1_Y' : [0,1,2,3,4,3,2,1,0,-1],
})
tuples = [((t, k.split('_')[0][0], int(k.split('_')[0][1:]), k.split('_')[1]), v[i])
for k,v in d.items() for i,t in enumerate(time) ]
df = pd.Series(dict(tuples)).unstack(-1)
df.index.names = ['time', 'group', 'id']
interval_ms = 1000
delay_ms = 2000
ani = animation.FuncAnimation(fig, plots, frames=df.groupby('time'), interval=interval_ms, repeat_delay=delay_ms,)
plt.show()
解决方案
编辑 3:我已删除所有以前的更新以保持清洁;您仍然可以在编辑历史记录中查看它们。
查看此代码是否符合您的要求,更改通过注释标记:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import pandas as pd
import numpy as np #<< a new import is required
DATA_LIMITS = [0, 15]
def datalimits(*data):
return DATA_LIMITS
fig = plt.figure(figsize=(10,18))
grid = plt.GridSpec(1, 3, wspace=0.4, hspace=0.3)
gridsize = (3, 2)
ax1 = plt.subplot2grid(gridsize, (0, 0), colspan=2, rowspan=2)
ax2 = plt.subplot2grid(gridsize, (2, 0), colspan=2, rowspan=2)
ax1.grid(False)
ax2.grid(False)
ax1.set_xlim(DATA_LIMITS)
ax1.set_ylim(DATA_LIMITS)
line_a, = ax1.plot([], [], 'o', c='red', alpha = 0.5, markersize=5,zorder=3)
line_b, = ax1.plot([], [], 'o', c='blue', alpha = 0.5, markersize=5,zorder=3)
lines=[line_a,line_b]
scat = ax1.scatter([], [], s=20, marker='o', c='white', alpha = 1,zorder=3)
scats=[scat]
line_d = ax2.plot([], [], '-', c = 'k') ##<< using '-' makes this a line plot
ax2.set_ylim(-6,6)
ax2.set_xlim(0,15)
def plots(tdf, xlim=None, ylim=None, fig=fig, ax=ax1):
df = tdf[1]
if xlim is None: xlim = datalimits(df['X'])
if ylim is None: ylim = datalimits(df['Y'])
for (group, gdf), group_line in zip(df.groupby('group'), lines+scats+line_d):
if group in ['A','B']: #<< 'D' is moved to a new if case
group_line.set_data(*gdf[['X','Y']].values.T)
elif group in ['D']:
if tdf[0]==0: #<< use this to "reset the line" when the animation restarts
## or remove the if/else part here if you want continuous (over-)plotting
group_line.set_data([0,0])
else:
_x,_y=group_line.get_data()
_x=np.append(_x,gdf['X'].values)
_y=np.append(_y,gdf['Y'].values)
group_line.set_data([_x,_y])
elif group in ['C']:
gdf['X'].values, gdf['Y'].values
scat.set_offsets(gdf[['X','Y']].values)
return [scat] + [line_a,line_b] + [line_d]
n = 9
time = range(n)
d = ({
'A1_X' : [13,14,12,13,11,12,13,12,11,10],
'A1_Y' : [6,6,7,7,7,8,8,8,9,10],
'A2_X' : [7,6,5,7,6,3,4,5,6,6],
'A2_Y' : [11,12,11,10,11,12,10,11,10,9],
'B1_X' : [8,9,8,7,6,7,5,6,7,6],
'B1_Y' : [3,4,3,2,3,4,2,1,2,3],
'B2_X' : [13,14,14,14,13,13,13,12,12,12],
'B2_Y' : [5,4,3,2,4,5,4,6,3,3],
'C1_X' : [5,6,7,5,6,5,6,5,6,5],
'C1_Y' : [10,11,10,11,12,11,10,8,7,6],
'D1_X' : [0,1,2,3,4,5,6,7,8,9],
'D1_Y' : [0,1,2,3,4,3,2,1,0,-1],
})
tuples = [((t, k.split('_')[0][0], int(k.split('_')[0][1:]), k.split('_')[1]), v[i])
for k,v in d.items() for i,t in enumerate(time) ]
df = pd.Series(dict(tuples)).unstack(-1)
df.index.names = ['time', 'group', 'id']
interval_ms = 1000
delay_ms = 2000
ani = animation.FuncAnimation(fig, plots, frames=df.groupby('time'), interval=interval_ms, repeat_delay=delay_ms,)
plt.show()
推荐阅读
- python - re.findall() 查找所有包含负项的二元组
- postgresql - 为什么从数据库 postgresql 生成实体会引发很多错误?
- visual-studio - 从 Visual Studio 重新启动时测试过程未终止
- java - GPS位置的反距离加权插值
- ios - 如何使用 FBInstreamAdView 修复我的错误
- scichart - 使自定义 SciChart 注释在图形上可移动
- javascript - 单击其他菜单项时隐藏当前子菜单
- qt - QwtScaleWidget::scaleDivChanged 仅适用于旧语法
- c# - 在 .Net Core 2 中使用 Guid.NewGuid() 获取随机实体(包括子实体)
- r - 返回与“summarise”返回的值相关联的列的值,用于另一列