【问题标题】:Animating Matplotlib/Seaborn plots through Pandas?通过 Pandas 动画 Matplotlib/Seaborn 情节?
【发布时间】:2020-07-30 23:08:49
【问题描述】:

我一直在尝试使用matplotlib.animation 为一系列情节制作动画,但无济于事。我的数据当前存储在 Pandas 数据框中,我想遍历一个类别(在本例中为颜色)并绘制与每种颜色对应的数据,如下所示:

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)

但是,此代码产生了 4 个问题:

  1. 即使我将动画保存到 ani 变量中,它似乎也没有显示与每种不同颜色相关的数据。

  2. 标题没有为每种颜色正确显示/更新。

  3. 调用ax.legend 会产生以下错误/警告:No handles with labels found to put in legend.

  4. 尝试保存动画会产生以下错误:MovieWriterRegistry' object is not an iterator

有人能解释一下为什么目前会出现这些问题吗?有没有更好的方法来编写/格式化我的动画代码?

【问题讨论】:

    标签: python matplotlib animation plot seaborn


    【解决方案1】:

    您的问题是您正在通过调用plt.clf() 删除循环中的ax 对象。相反,您应该调用 plt.cla() 来清除坐标区的内容,而不是坐标区本身。

    但是,由于您正在清除坐标区,它们会恢复到原来的状态,因此您可能还需要在 animate 函数中重置坐标区限制和格式

    【讨论】:

      【解决方案2】:

      看看这段代码:

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

      我编辑了一些东西:

      1. 正如@Diziet Asahi 已经解释的那样,我将plt.clf() 替换为ax.cla(),以便在每一帧清理轴
      2. update函数中移动了绘图设置(set_xlabelset_xlimset_xticks等):这样每个周期都会调整图形,因此在整个动画过程中它是固定的
      3. 如果您不对过滤后的数据框fil_test 进行排序,则图例和颜色关联将相对于该数据框中出现的第一个值发生变化。为了避免这种情况,我添加了fil_test = fil_test.sort_values(by = ['shape']):这样'cube''sphere' 的颜色-图例关联在整个动画中都是固定的
      4. 添加了fig.subplots_adjust(top = 0.88, right = 0.85, bottom = 0.11, left = 0.12) 以便为图例腾出一些空间
      5. set_title中的r-string替换为f-string,以固定标题的长度以提高其可读性

      结果:

      【讨论】:

      • 似乎 ax.cla() 是完成这项工作的关键!我想做一些额外的定制,但我可以自己解决。感谢您的帮助!
      猜你喜欢
      • 2014-06-07
      • 2020-08-16
      • 2019-01-14
      • 2018-04-13
      • 1970-01-01
      • 2020-06-13
      • 2019-03-22
      • 2017-01-31
      • 2016-11-24
      相关资源
      最近更新 更多