简体   繁体   English

通过 Pandas 对 Matplotlib/Seaborn 绘图进行动画处理?

[英]Animating Matplotlib/Seaborn plots through Pandas?

I've been trying to animate a series of plots using matplotlib.animation to no avail.我一直在尝试使用matplotlib.animation为一系列情节制作动画,但无济于事。 My data are currently stored in a Pandas dataframe and I want to iterate through a category (in this case, colors) and plot the data corresponding to each color as the following:我的数据当前存储在 Pandas dataframe 中,我想遍历一个类别(在本例中为颜色)和 plot 与每种颜色对应的数据如下:

import pandas as pd
import seaborn as sns
import matplotlib.animation as animation

def update_2(i):
    plt.clf()
    fil_test = test[test['color'] == iterations[i]]
    sns.scatterplot(x = 'size',y = 'score',hue = 'shape',ci = None,
                              palette = 'Set1',data = fil_test)
    ax.set_title(r"Score vs. Size: {} Shapes".format(
        iterations[i]),fontsize = 20)
    ax.legend(loc='center left', bbox_to_anchor=(1, 0.5),prop={'size': 12})


test = pd.DataFrame({'color':["red", "blue", "red", 
"yellow",'red','blue','yellow','yellow','red'], 
        'shape': ["sphere", "sphere", "sphere", 
"cube",'cube','cube','cube','sphere','cube'], 
        'score':[1,7,3,8,5,8,6,2,9],
        'size':[2,8,4,7,9,8,3,2,1]})
iterations = test['color'].unique()
i = 0
fig2 = plt.figure(figsize = (8,8))
ax = plt.gca()
plt.axis()
ax.set_xlabel("size",fontsize = 16)
ax.set_ylabel("score",fontsize = 16)
ax.set_xlim(0,10)
ax.set_xlim(0,10)
ax.set_xticks(np.linspace(0,10,6))
ax.set_yticks(np.linspace(0,10,6))
ax.tick_params(axis='both', which='major', labelsize=15)

ani = animation.FuncAnimation(fig2,update_2,frames = len(iterations))
ani.save("test.mp4", dpi=200, fps=1)

However, 4 issues arise from this code:但是,此代码产生了 4 个问题:

  1. Even though I saved my animation to the ani variable, it doesn't seem to display the data associated with each different color.即使我将 animation 保存到ani变量中,它似乎也没有显示与每种不同颜色相关的数据。

  2. The title doesn't show up/update appropriately for each color.标题没有针对每种颜色适当地显示/更新。

  3. Calling on ax.legend produces the following error/Warning: No handles with labels found to put in legend.调用ax.legend会产生以下错误/警告: No handles with labels found to put in legend.

  4. Trying to save the animation produces the following Error: MovieWriterRegistry' object is not an iterator尝试保存 animation 会产生以下错误: MovieWriterRegistry' object is not an iterator

Could someone explain why these issues currently pop up and is there a better way to write/format my code for animated plots?有人可以解释为什么当前会出现这些问题,是否有更好的方法来编写/格式化我的动画代码代码?

Have a look to this code:看看这段代码:

import pandas as pd
import seaborn as sns
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np

test = pd.DataFrame({'color': ['red', 'blue', 'red', 'yellow', 'red', 'blue', 'yellow', 'yellow', 'red'],
                     'shape': ['sphere', 'sphere', 'sphere', 'cube', 'cube', 'cube', 'cube', 'sphere', 'cube'],
                     'score': [1, 7, 3, 8, 5, 8, 6, 2, 9],
                     'size': [2, 8, 4, 7, 9, 8, 3, 2, 1]})
iterations = test['color'].unique()

fig, ax = plt.subplots(figsize = (10, 8))
fig.subplots_adjust(top = 0.88, right = 0.85, bottom = 0.11, left = 0.12)

def update(i):
    ax.cla()
    fil_test = test[test['color'] == iterations[i]]
    fil_test = fil_test.sort_values(by = ['shape'])
    sns.scatterplot(x = 'size', y = 'score', hue = 'shape', ci = None, palette = 'Set1', data = fil_test)
    ax.set_title(f'Score vs. Size: {format(iterations[i]):>6} Shapes', fontsize = 20)
    ax.legend(loc = 'center left', bbox_to_anchor = (1, 0.5), prop = {'size': 12})
    ax.set_xlabel('size', fontsize = 16)
    ax.set_ylabel('score', fontsize = 16)
    ax.set_xlim(0, 10)
    ax.set_xlim(0, 10)
    ax.set_xticks(np.linspace(0, 10, 6))
    ax.set_yticks(np.linspace(0, 10, 6))
    ax.tick_params(axis = 'both', which = 'major', labelsize = 15)

ani = animation.FuncAnimation(fig, update, frames = len(iterations))
ani.save('test.mp4', dpi=200, fps=1)

plt.show()

I edited some things:我编辑了一些东西:

  1. as already explained by @Diziet Asahi , I replaced plt.clf() with ax.cla() in order to clean the axis at each frame正如@Diziet Asahi已经解释的那样,我用plt.clf()替换了 plt.clf ax.cla()以清洁每一帧的轴
  2. moved plotting settings ( set_xlabel , set_xlim , set_xticks and so on) inside update function: in this way the figure is adjusted every cycle so it is fixed throughout the animationupdate function 中移动了绘图设置( set_xlabelset_xlimset_xticks等):通过这种方式,每个周期都会调整图形,因此它在整个 animation 中都是固定的
  3. if you do not sort the filtered dataframe fil_test , the legend and color association will change with respect to the first value present in that dataframe.如果您不对过滤后的 dataframe fil_test进行排序,则图例和颜色关联将相对于 dataframe 中存在的第一个值发生变化。 In order to avoid that, I added fil_test = fil_test.sort_values(by = ['shape']) : in this way the color-legend association for 'cube' and 'sphere' is fixed throughout the animation为了避免这种情况,我添加了fil_test = fil_test.sort_values(by = ['shape']) :这样, 'cube''sphere'的颜色-图例关联在整个 animation 中都是固定的
  4. added fig.subplots_adjust(top = 0.88, right = 0.85, bottom = 0.11, left = 0.12) in order to make some space for the legend添加了fig.subplots_adjust(top = 0.88, right = 0.85, bottom = 0.11, left = 0.12)以便为图例腾出一些空间
  5. replaced r-string with f-string in set_title in order to fix the length of the title so as to improve its readabilityset_title中将 r-string 替换为 f-string 以固定标题的长度以提高其可读性

Result:结果:

在此处输入图像描述

Your issue is that you are deleting the ax object in your loop by calling plt.clf() .您的问题是您通过调用plt.clf()删除循环中的ax object 。 Instead, you should call plt.cla() which clear the content of the axes, but not the Axes themselves.相反,您应该调用plt.cla()来清除轴的内容,而不是轴本身。

However, since you are clearing the axes, they go back to their original state, so you will probably want to reset the axes limit and formatting in the animate function as well但是,由于您正在清除轴,它们 go 回到原来的 state,因此您可能还需要在animate ZC1C425268E68385D1AB5074C17A94F14 中重置轴限制和格式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM