2

Maybe you can help me. I'm trying to animate some bars together with a plot in matplotlib. For example, here's some code (only the bars) which is working fine:

from matplotlib import pyplot as plt
from matplotlib.animation import ArtistAnimation
import numpy as np

fig = plt.figure()
x = [1,2,3,4,5]
y = [5,7,2,5,3]

y_steps = []
for i in range(len(y)):
    y_steps.append(np.linspace(0, y[i], 50))

data = []
for i in range(len(y_steps[0])):
    data.append([y_steps[j][i] for j in range(len(y))])

ims = []
for i in range(len(y_steps[0])):
    pic = plt.bar(x, data[i], color='c')
    ims.append(pic)

anim = ArtistAnimation(fig, ims, interval=40)
plt.show()

But now I want some lines to grow together with the bars. I've tried a lot and googled a lot, but I am not able to make it work. For your understandig, I'm pasting my idea (of the not-working-code) here:

from matplotlib import pyplot as plt
from matplotlib.animation import ArtistAnimation
import numpy as np

fig = plt.figure()

x = [1,2,3,4,5]
y = [5,7,2,5,3]

y_steps = []
for i in range(len(y)):
    y_steps.append(np.linspace(0, y[i], 50))

data = []
for i in range(len(y_steps[0])):
    data.append([y_steps[j][i] for j in range(len(y))])

ims = []
for i in range(len(y_steps[0])):
    pic_1 = plt.bar(x, data[i], color='c')
    pic_2 = plt.plot(x, data[i], color='r')
    ims.append([pic_1, pic_2])

anim = ArtistAnimation(fig, ims, interval=40)
plt.show()

It looks like all the pictures, saved in ims, are shown at once and there's no animation.

Maybe someone of you can help me. Thanks a lot.

1 Answer 1

4

When using ArtistAnimation(fig, ims, ...), ims is expected to be a list of Artists. [pic_1, pic_2] is a list, not an Artist. ims.append([pic_1, pic_2]) appends the list as a single object to ims.

The simplest way to fix the problem is to change ims.append([pic_1, pic_2]) to

ims.extend([pic_1, pic_2])

because ims.extend([pic_1, pic_2]) appends pic_1 and pic_2 into ims separately.

You can see the difference between append and extend by playing with this example:

In [41]: x = []

In [42]: x.append([1, 2])

In [43]: x
Out[43]: [[1, 2]]   # x is a list containing 1 item which happens to be a list

In [44]: y = []

In [45]: y.extend([1,2])

In [46]: y
Out[46]: [1, 2]     # y is a list containing 2 items

Although that provides a quick fix, the result is rather "blinky". To make a smoother animation, avoid calling plt.bar and plt.plot so many times. It is more efficient to call each once, and then use the Rectangle.set_height and Line2D.set_data methods to modify the existing Rectangles and Line2Ds:

from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np

fig = plt.figure()

x = [1,2,3,4,5]
y = [5,7,2,5,3]

data = np.column_stack([np.linspace(0, yi, 50) for yi in y])

rects = plt.bar(x, data[0], color='c')
line, = plt.plot(x, data[0], color='r')
plt.ylim(0, max(y))
def animate(i):
    for rect, yi in zip(rects, data[i]):
        rect.set_height(yi)
    line.set_data(x, data[i])
    return rects, line

anim = animation.FuncAnimation(fig, animate, frames=len(data), interval=40)
plt.show()
Sign up to request clarification or add additional context in comments.

1 Comment

That's more than perfect! Exactly what I was looking for. Thank you very much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.