Reputation: 124
I have this dataframe called vars
and I'm trying to plot an animated line chart, with each column being one line (except the date column that would be the x axis).
data var_brl var_ars var_bob var_clp var_cop var_mxn var_pen var_pyg var_uyu
0 01/01/2020 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
1 02/01/2020 0.17 -0.10 0.14 -0.36 -1.01 -0.49 -0.41 0.41 0.16
2 03/01/2020 1.19 -0.22 0.07 1.65 -1.01 -0.04 0.11 0.49 -0.38
3 04/01/2020 1.19 -0.22 0.07 1.65 -1.01 -0.04 0.11 0.49 -0.38
4 05/01/2020 1.19 -0.22 0.07 1.65 -1.01 -0.04 0.11 0.49 -0.38
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
135 15/05/2020 45.71 13.03 -0.07 10.07 18.98 26.43 3.78 1.81 18.19
136 16/05/2020 45.71 13.03 -0.07 10.07 18.98 26.43 3.78 1.81 18.19
137 17/05/2020 45.71 13.03 -0.07 10.07 18.98 26.43 3.78 1.81 18.19
138 18/05/2020 42.32 13.28 0.00 8.92 17.20 25.49 3.47 2.09 18.06
139 19/05/2020 43.20 13.43 0.00 8.88 16.69 25.08 3.46 2.10 18.06
This the code I'm using:
fig, ax = plt.subplots(figsize=(16, 8))
plt.style.use('ggplot')
months = mdates.MonthLocator()
months_fmt = mdates.DateFormatter('%m/%Y')
ax.xaxis.set_major_locator(months)
ax.xaxis.set_major_formatter(months_fmt)
limx_i = vars.iloc[0, 0]
limx_f = vars.iloc[-1, 0]
limy_f = vars.iloc[:, 1:].max().max()
limy_i = vars.iloc[:, 1:].min().min()
ax.set_xlim(limx_i, limx_f + dt.timedelta(days=30))
ax.set_ylim(limy_i, limy_f)
line, = [ax.plot([], [], lw=2)]
for i in range(1, vars.shape[1]):
def animate(i):
line.set_data(vars['data'], vars.iloc[:, i])
return line,
ani = animation.FuncAnimation(fig, animate, frames=140, interval=20, blit=True)
ax.tick_params(bottom=False, top=False, right=False, left=False)
ax.set_ylabel('Oscilação acumulada %')
plt.grid(False)
for key, spine in ax.spines.items():
spine.set_visible(False)
plt.tight_layout()
plt.show()
I need to iterate over the dataframe because the code must work regardless of the number of columns.
It plots the image above (with no lines) and then it raises the following error:
AttributeError: 'list' object has no attribute 'set_data'
I'm kind of inexperienced with animations so any help will be much appreciated. Can anyone see what I'm doing wrong?
[EDIT]
I'm looking for an animation like this:
But with a line for each column. And I can't figure out how to build an animated chart like this with multiple lines.
I understand that I have to use FuncAnimation
from matplotlib.animation
but I'm having problems with it.
I got this char from this Towards Data Science post.
Upvotes: 1
Views: 1288
Reputation: 2602
You want to avoid using vars
as a variable name because it is a builtin function in Python. You can loop over the columns as shown in the for loop below.The animation can be achieved by using matplotlib's interactive mode in the following way:
import pandas as pd
from datetime import date, datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib.dates as md
# test file
df = pd.read_csv('test.txt',sep='\s+')
def convert_date(df):
return datetime.strptime(df['data'], '%d/%m/%Y')
df['data'] = df.apply(convert_date, axis=1)
fig, ax = plt.subplots()
limx_i = df.iloc[0, 0]
limx_f = df.iloc[-1, 0]
limy_f = df.iloc[:, 1:].max().max()
limy_i = df.iloc[:, 1:].min().min()
ax.set_xlim(limx_i, limx_f)
ax.set_ylim(limy_i, limy_f)
plt.ion() # set interactive mode
plt.show()
for i,row in df.iterrows():
plt.cla()
df.iloc[:i+1,:].plot(x='data', ax=ax)
ax.set_xlim(limx_i, limx_f)
ax.set_ylim(limy_i, limy_f)
plt.legend(loc='upper right')
plt.gcf().canvas.draw()
plt.pause(0.1)
Upvotes: 2