Search code examples
pythonpandasmatplotlibseaborn

How to animate a line graph in python where each step of the animation draws an entirely new line based on data in dataframe, and export as gif


I would like to animate a line graph in python based on data in my df.

  • For each step in the animation, a line graph would be displayed using one row of the df.
  • A fraction of a second later, a new line graph would be displayed using the next row of data in the df.
  • This process would continue until each row of data had been separately displayed.
  • After this process had been done for all rows, the graph would show the last line of data.
  • I would also have code that converts the animation to a gif and then exports it.

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

Solution

  • 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")