I would like to animate a line graph in python based on data in my df.
I'm lost as to how to do this and was hoping someone could point me in the right direction.
Here is the code and df I have so far:
# Import dependencies
import pandas as pd
from datetime import datetime
# Create lists to be converted to df
data = [['01/01/2016', 4.17, 4.42, 4.53, 4.71, 4.77, 4.72],
['02/05/2017', 4.59, 4.64, 4.70, 4.74, 4.80, 4.68],
['04/17/2018', 4.67, 4.82, 4.90, 5.02, 5.20, 5.06],
['03/03/2019', 4.70, 4.79, 4.90, 4.80, 4.50, 3.84],
['08/21/2021', 6.02, 5.47, 5.34, 5.55, 5.44, 5.25],
['09/14/2022', 5.18, 5.25, 5.36, 5.37, 5.27, 4.74],
['05/05/2023', 5.32, 5.47, 5.46, 5.52, 5.53, 4.64]
]
# Create the pandas df
df = pd.DataFrame(data, columns=['date', 'Month 1', 'Month 2', 'Month 3',
'Month 4', 'Month 5', 'Month 6'])
# Convert 'date' to datetime.
df['date'] = pd.to_datetime(df['date'], format='%m/%d/%Y')
# Display df
display(df)
# Create animated line graph as described in my question
To make an animation you can read the guide in the documentation. Essentially, you will need to create the empty figure and plot a blank line, saving the return of that. Then you will have to create a function that takes the frame number and updates the plot accordingly. I'm assuming your x-axis is the months, so I changed the ticks to have the appropriate text. The FuncAnimation
returns an object that you can then use to save the animation as a gif.
Note: Rather than letting the func
use variables from the global scope, I use functools.partial
to pass the arguments to the function and just leave the frame number left for the animation to iterate through.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
from functools import partial
fig, ax = plt.subplots()
line, = ax.plot([], [])
xlabels = df.columns[1:].tolist()
x = np.arange(len(xlabels))
ax.set_xticks(ticks=x, labels=xlabels)
ax.set_ylim(df.loc[:,xlabels].min().min(), df.loc[:,xlabels].max().max())
def func_full(i, df, line, x, xlabels):
line.set_data(x, df.loc[i, xlabels])
func = partial(func_full, df=df, line=line, x=x, xlabels=xlabels)
ani = FuncAnimation(fig, func, frames=len(df), interval=500)
ani.save("temp.gif", fps=1, writer="pillow")