0

I have a running times dataset that I have broken down into six months (Jan - Jun). I want to plot an animation of a scatter plot showing distance on the x-axis and time on the y-axis.

Without any animations I have:

plt.figure(figsize = (8,8))

plt.scatter(data = strava_df, x = 'Distance', y = 'Elapsed Time', c = col_list, alpha = 0.7)
plt.xlabel('Distance (km)')
plt.ylabel('Elapsed Time (min)')
plt.title('Running Distance vs. Time')
plt.show()

Which gives me:

enter image description here

What I'd like is an animation that plots the data for the first month, then after a delay the second month, and so on.

from matplotlib.animation import FuncAnimation
fig = plt.figure(figsize=(10,10))
ax = plt.axes(xlim=(2,15), ylim=(10, 80))

x = []
y = []
scat = plt.scatter(x, y)

def animate(i):
    for m in range(0,6):
        x.append(strava_df.loc[strava_df['Month'] == m,strava_df['Distance']])
        y.append(strava_df.loc[strava_df['Month'] == m,strava_df['Elapsed Time']])
    

FuncAnimation(fig, animate, frames=12, interval=6, repeat=False)

plt.show()

This is what I've come up with, but it isn't working. Any advice?

DillM94
  • 71
  • 4

1 Answers1

0

The animate function should update the matplotlib object created by a call to scat = ax.scatter(...) and also return that object as a tuple. The positions can be updated calling scat.set_offsets() with an nx2 array of xy values. The color can be updated with scat.set_color() with a list or array of colors.

Supposing col_list is a list of color names or rgb-values, the code could look like:

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import pandas as pd
import numpy as np

strava_df = pd.DataFrame({'Month': np.random.randint(0, 6, 120),
                          'Distance': np.random.uniform(2, 13, 120),
                          'Color': np.random.choice(['blue', 'red', 'orange', 'cyan'], 120)
                          })
strava_df['Elapsed Time'] = strava_df['Distance'] * 5 + np.random.uniform(0, 5, 120)

fig = plt.figure(figsize=(10, 10))
ax = plt.axes(xlim=(2, 15), ylim=(10, 80))

scat = ax.scatter([], [], s=20)

def animate(i):
     x = np.array([])
     y = np.array([])
     c = np.array([])
     for m in range(0, i + 1):
          x = np.concatenate([x, strava_df.loc[strava_df['Month'] == m, 'Distance']])
          y = np.concatenate([y, strava_df.loc[strava_df['Month'] == m, 'Elapsed Time']])
          c = np.concatenate([c, strava_df.loc[strava_df['Month'] == m, 'Color']])
     scat.set_offsets(np.array([x, y]).T)
     scat.set_color(c)
     return scat,

anim = FuncAnimation(fig, animate, frames=12, interval=6, repeat=False)
plt.show()
JohanC
  • 71,591
  • 8
  • 33
  • 66
  • When I run this code in Jupyter Notebook I get no output. Am I missing something? – DillM94 Jul 21 '21 at 10:19
  • 1
    Probably you need `%matplotlib notebook` instead of `%matplotlib inline` to get an "interactive" inline plot instead of just an image. See a.o. [this post](https://stackoverflow.com/questions/47185277/show-plot-in-new-interactive-window-in-jupyter-with-python-3-6) and links from there. Things can be different depending on your environment and matplotlib version. The docs can be confusing. – JohanC Jul 21 '21 at 10:38