【问题标题】:Animating 2 lines on the same plot in python's matplotlib在 python 的 matplotlib 中的同一图上动画 2 行
【发布时间】:2020-11-17 08:12:25
【问题描述】:

我正在尝试为同一情节上的两条线设置动画。在四处搜索之后,我遇到了this post,这似乎让我走上了正轨。当我运行此代码时,停滞图显示没有动画,给我一个错误AttributeError: 'AxesSubplot' object has no attribute 'set_data'。我查了set_data,它说它“接受:二维数组(行是x,y)或两个一维数组”。由于我将line1line2 分配给绘图而不是二维数组,因此动画是否不起作用?我将不胜感激任何帮助让这些线条在我的情节上制作动画,我尝试并尝试无济于事。谢谢!

fig, ax = plt.subplots(figsize=(16,8))

#Plot Lines
line1 = sns.lineplot('game_seconds_remaining', 'away_wp', data=game, color='#4F2683',linewidth=2)
line2 = sns.lineplot('game_seconds_remaining', 'home_wp', data=game, color='#869397',linewidth=2)
#Add Fill
ax.fill_between(game['game_seconds_remaining'], 0.5, game['away_wp'], where=game['away_wp']>.5, color = '#4F2683',alpha=0.3)
ax.fill_between(game['game_seconds_remaining'], 0.5, game['home_wp'], where=game['home_wp']>.5, color = '#869397',alpha=0.3)


#Plot Aesthetics - Can Ignore
plt.ylabel('Win Probability %', fontsize=16)
plt.xlabel('', fontsize=16)
plt.axvline(x=900, color='white', alpha=0.7)
plt.axvline(x=1800, color='white', alpha=0.7)
plt.axvline(x=2700, color='white', alpha=0.7)
plt.axhline(y=.50, color='white', alpha=0.7)
plt.suptitle('Minnesota Vikings @ Dallas Cowboys', fontsize=20, style='italic',weight='bold')
plt.title('Min 28, DAL 24 - Week 10 ', fontsize=16, style = 'italic',weight='semibold')


#Labels (And variable assignment for animation below)
x = ax.set_xticks(np.arange(0, 3601,900))
y1 = game['away_wp']
y2 = game['home_wp']
plt.gca().invert_xaxis()
x_ticks_labels = ['End','End Q3','Half','End Q1','Kickoff']
ax.set_xticklabels(x_ticks_labels, fontsize=12)


#Animation - Not working
def update(num, x, y1, y2, line1, line2):
    line1.set_data(x[:num], y1[:num])
    line2.set_data(x[:num], y2[:num])
    return [line1,line2]

ani = animation.FuncAnimation(fig, update, len(x), fargs=[x, y1, y2, line1, line2],
                  interval=295, blit=False)

【问题讨论】:

  • 只有当你使用matplotlib 函数来画线时它才会起作用——即。 plt.plot()seaborn 可能需要更多代码才能从 AxesSubplot 获取线路
  • @furas plt.plot() 仍然返回非动画图
  • 你是用line1, = plt.plot(...) 代替sns.lineplot()吗?
  • @furas 正确。也试过ax.plot(...)
  • 等一下,line1, = plt.plot(...)line1 = plt.plot(...) 返回不同的东西。带逗号的那个把它搞砸了。两者都没有动画。

标签: python pandas dataframe matplotlib animation


【解决方案1】:

似乎sns 给出了AxesSublot,你必须得到line(s) 这个Axes

ax1 = sns.lineplot(...)
ax2 = sns.lineplot(...)

line1 = ax1.lines[0]
line2 = ax2.lines[1]

或者(因为两条线都在同一个Axes

sns.lineplot(x=x, y='away_wp', data=game)
sns.lineplot(x=x, y='home_wp', data=game)

ax = plt.gca()

line1 = ax.lines[0]
line2 = ax.lines[1]

编辑:

对于Google Colab 它需要

from matplotlib import rc
rc('animation', html='jshtml')

# code without `plt.show()`

ani   # display it

来源:Embedding Matplotlib Animations in Python (google colab notebook)


随机数据的最小工作代码

import random
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import animation
from matplotlib import rc
rc('animation', html='jshtml')

game = pd.DataFrame({
    'away_wp': [random.randint(-10,10) for _ in range(100)],
    'home_wp': [random.randint(-10,10) for _ in range(100)],
    'game_seconds_remaining': list(range(100)),
})

x = range(len(game))
y1 = game['away_wp']
y2 = game['home_wp']

fig = plt.gcf()
ax = plt.gca()

sns.lineplot(x='game_seconds_remaining', y='away_wp', data=game)
sns.lineplot(x='game_seconds_remaining', y='home_wp', data=game)

line1 = ax.lines[0]
line2 = ax.lines[1]

ax.fill_between(game['game_seconds_remaining'], 0.5, game['away_wp'], where=game['away_wp']>.5, color = '#4F2683',alpha=0.3)
ax.fill_between(game['game_seconds_remaining'], 0.5, game['home_wp'], where=game['home_wp']>.5, color = '#869397',alpha=0.3)
#print(ax.collections)

def update(num, x, y1, y2, line1, line2):
    line1.set_data(x[:num], y1[:num])
    line2.set_data(x[:num], y2[:num])

    ax.collections.clear()
    ax.fill_between(game['game_seconds_remaining'][:num], 0.5, game['away_wp'][:num], where=game['away_wp'][:num]>.5, color = '#4F2683',alpha=0.3)
    ax.fill_between(game['game_seconds_remaining'][:num], 0.5, game['home_wp'][:num], where=game['home_wp'][:num]>.5, color = '#869397',alpha=0.3)

    return line1,line2

ani = animation.FuncAnimation(fig, update, len(x), fargs=[x, y1, y2, line1, line2], interval=295, blit=False)

#plt.show()

ani   # display it

编辑:

同样没有seaborn,但只有plt.plot()

一开始我创建空行line1, = plt.plot([], [])

import random
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import animation
from matplotlib import rc
rc('animation', html='jshtml')

game = pd.DataFrame({
    'away_wp': [random.randint(-10,10) for _ in range(100)],
    'home_wp': [random.randint(-10,10) for _ in range(100)],
    'game_seconds_remaining': list(range(100)),
})

x = range(len(game))
y1 = game['away_wp']
y2 = game['home_wp']

fig = plt.gcf()
ax = plt.gca()

# empty lines at start
line1, = plt.plot([], [])
line2, = plt.plot([], [])

# doesn't draw fill_between at start

# set limits 
ax.set_xlim(0, 100)
ax.set_ylim(-10, 10)

def update(num, x, y1, y2, line1, line2):
    line1.set_data(x[:num], y1[:num])
    line2.set_data(x[:num], y2[:num])
    # autoscale 
    #ax.relim()
    #ax.autoscale_view()

    ax.collections.clear()
    ax.fill_between(game['game_seconds_remaining'][:num], 0.5, game['away_wp'][:num], where=game['away_wp'][:num]>.5, color = '#4F2683',alpha=0.3)
    ax.fill_between(game['game_seconds_remaining'][:num], 0.5, game['home_wp'][:num], where=game['home_wp'][:num]>.5, color = '#869397',alpha=0.3)
    
    return line1,line2

ani = animation.FuncAnimation(fig, update, len(x), fargs=[x, y1, y2, line1, line2], interval=295, blit=False)

#plt.show()

ani

【讨论】:

  • 我复制了这个确切的代码,我得到一个没有动画的空白图。如果这很重要,我在 google colab。
  • 我正常运行python script.py。我从来没有尝试在 Google Colab 中这样做。也许它需要更多的东西来显示动画。也许是一些神奇的功能%
  • Matplotlib animate fill_between shape - 在update() 中,您必须将其删除ax.colections.clear() 并使用[:num] 再次绘制
  • 我在示例中的update() 中添加了fill_between()
猜你喜欢
  • 1970-01-01
  • 2020-10-07
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多