In this quick tutorial, I’ll show you how to create an animated scatterplot using the libraries matplotlib
or seaborn
and imageio
. Here’s the GitHub repo of this project.
The scatterplot illustrates the relationship between life expectancy and fertility rate of world’s countries from 1960 to 2015, based on the Gapminder data set:
country | year | population | life_expectancy | fertility_rate | continent | |
---|---|---|---|---|---|---|
0 | Afghanistan | 1800 | 3280000.0 | 28.21 | 7.0 | Asia |
The animated scatterplot is basically made of several overlapping static plots. Here’s how to create the animation step-by-step:
1. Create static scatterplots for each year in the data set.
The scatterplots depict life_expectancy
on the x axis and fertility_rate
on the y axis. To make the plots even more insightful, the size of the points illustrates the population
number and their color illustrates the continent
.
<span>import</span> <span>matplotlib.pyplot</span> <span>as</span> <span>plt</span><span>%</span><span>matplotlib</span> <span>inline</span><span>import</span> <span>seaborn</span> <span>as</span> <span>sns</span><span>sns</span><span>.</span><span>scatterplot</span><span>(</span><span>x</span><span>=</span><span>'</span><span>life_expectancy</span><span>'</span><span>,</span><span>y</span><span>=</span><span>'</span><span>fertility_rate</span><span>'</span><span>,</span><span>hue</span><span>=</span><span>'</span><span>continent</span><span>'</span><span>,</span><span>size</span><span>=</span><span>'</span><span>population</span><span>'</span><span>,</span><span>sizes</span><span>=</span><span>(</span><span>10</span><span>,</span> <span>1000</span><span>),</span><span>legend</span><span>=</span><span>False</span><span>,</span><span>data</span><span>=</span><span>gapminder_df</span><span>.</span><span>loc</span><span>[</span><span>gapminder_df</span><span>[</span><span>'</span><span>year</span><span>'</span><span>]</span><span>==</span><span>year</span><span>],</span><span>alpha</span><span>=</span><span>0.7</span><span>,</span><span>palette</span><span>=</span><span>'</span><span>Set2</span><span>'</span><span>)</span><span>plt</span><span>.</span><span>title</span><span>(</span><span>f</span><span>'</span><span>{</span><span>year</span><span>}</span><span>'</span><span>,</span> <span>loc</span><span>=</span><span>'</span><span>center</span><span>'</span><span>,</span> <span>fontsize</span><span>=</span><span>20</span><span>,</span> <span>color</span><span>=</span><span>'</span><span>black</span><span>'</span><span>,</span> <span>fontweight</span><span>=</span><span>'</span><span>bold</span><span>'</span><span>)</span><span>plt</span><span>.</span><span>xlabel</span><span>(</span><span>'</span><span>Life expectancy</span><span>'</span><span>)</span><span>plt</span><span>.</span><span>ylabel</span><span>(</span><span>'</span><span>Fertility rate</span><span>'</span><span>)</span><span>import</span> <span>matplotlib.pyplot</span> <span>as</span> <span>plt</span> <span>%</span><span>matplotlib</span> <span>inline</span> <span>import</span> <span>seaborn</span> <span>as</span> <span>sns</span> <span>sns</span><span>.</span><span>scatterplot</span><span>(</span><span>x</span><span>=</span><span>'</span><span>life_expectancy</span><span>'</span><span>,</span> <span>y</span><span>=</span><span>'</span><span>fertility_rate</span><span>'</span><span>,</span> <span>hue</span><span>=</span><span>'</span><span>continent</span><span>'</span><span>,</span> <span>size</span><span>=</span><span>'</span><span>population</span><span>'</span><span>,</span> <span>sizes</span><span>=</span><span>(</span><span>10</span><span>,</span> <span>1000</span><span>),</span> <span>legend</span><span>=</span><span>False</span><span>,</span> <span>data</span><span>=</span><span>gapminder_df</span><span>.</span><span>loc</span><span>[</span><span>gapminder_df</span><span>[</span><span>'</span><span>year</span><span>'</span><span>]</span><span>==</span><span>year</span><span>],</span> <span>alpha</span><span>=</span><span>0.7</span><span>,</span> <span>palette</span><span>=</span><span>'</span><span>Set2</span><span>'</span><span>)</span> <span>plt</span><span>.</span><span>title</span><span>(</span><span>f</span><span>'</span><span>{</span><span>year</span><span>}</span><span>'</span><span>,</span> <span>loc</span><span>=</span><span>'</span><span>center</span><span>'</span><span>,</span> <span>fontsize</span><span>=</span><span>20</span><span>,</span> <span>color</span><span>=</span><span>'</span><span>black</span><span>'</span><span>,</span> <span>fontweight</span><span>=</span><span>'</span><span>bold</span><span>'</span><span>)</span> <span>plt</span><span>.</span><span>xlabel</span><span>(</span><span>'</span><span>Life expectancy</span><span>'</span><span>)</span> <span>plt</span><span>.</span><span>ylabel</span><span>(</span><span>'</span><span>Fertility rate</span><span>'</span><span>)</span>import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns sns.scatterplot(x='life_expectancy', y='fertility_rate', hue='continent', size='population', sizes=(10, 1000), legend=False, data=gapminder_df.loc[gapminder_df['year']==year], alpha=0.7, palette='Set2') plt.title(f'{year}', loc='center', fontsize=20, color='black', fontweight='bold') plt.xlabel('Life expectancy') plt.ylabel('Fertility rate')
Enter fullscreen mode Exit fullscreen mode
2. Export the scatterplot images to a designated folder.
You need to save all the individual scatterplots, so that you can overlap the images in the next step.
<span>import</span> <span>imageio</span><span>import</span> <span>os</span><span>images</span> <span>=</span> <span>[]</span><span>folder</span><span>=</span><span>'</span><span>/path/to/folder/images</span><span>'</span><span>if</span> <span>not</span> <span>os</span><span>.</span><span>path</span><span>.</span><span>exists</span><span>(</span><span>folder</span><span>):</span><span>os</span><span>.</span><span>mkdir</span><span>(</span><span>folder</span><span>)</span><span>import</span> <span>imageio</span> <span>import</span> <span>os</span> <span>images</span> <span>=</span> <span>[]</span> <span>folder</span><span>=</span><span>'</span><span>/path/to/folder/images</span><span>'</span> <span>if</span> <span>not</span> <span>os</span><span>.</span><span>path</span><span>.</span><span>exists</span><span>(</span><span>folder</span><span>):</span> <span>os</span><span>.</span><span>mkdir</span><span>(</span><span>folder</span><span>)</span>import imageio import os images = [] folder='/path/to/folder/images' if not os.path.exists(folder): os.mkdir(folder)
Enter fullscreen mode Exit fullscreen mode
3. Join the individual images in chronological order.
<span>filename</span> <span>=</span> <span>f</span><span>'</span><span>lifeexp_</span><span>{</span><span>year</span><span>}</span><span>.png</span><span>'</span><span>plt</span><span>.</span><span>savefig</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>))</span><span>images</span><span>.</span><span>append</span><span>(</span><span>imageio</span><span>.</span><span>imread</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>)))</span><span>filename</span> <span>=</span> <span>f</span><span>'</span><span>lifeexp_</span><span>{</span><span>year</span><span>}</span><span>.png</span><span>'</span> <span>plt</span><span>.</span><span>savefig</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>))</span> <span>images</span><span>.</span><span>append</span><span>(</span><span>imageio</span><span>.</span><span>imread</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>)))</span>filename = f'lifeexp_{year}.png' plt.savefig(os.path.join(folder,filename)) images.append(imageio.imread(os.path.join(folder,filename)))
Enter fullscreen mode Exit fullscreen mode
4. Export the scatterplots sequence as a gif.
The fps
(frames per second) parameter sets the speed of the animation.
<span>imageio</span><span>.</span><span>mimsave</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>'</span><span>scatterplot.gif</span><span>'</span><span>),</span> <span>images</span><span>,</span> <span>fps</span><span>=</span><span>20</span><span>)</span><span>imageio</span><span>.</span><span>mimsave</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>'</span><span>scatterplot.gif</span><span>'</span><span>),</span> <span>images</span><span>,</span> <span>fps</span><span>=</span><span>20</span><span>)</span>imageio.mimsave(os.path.join(folder,'scatterplot.gif'), images, fps=20)
Enter fullscreen mode Exit fullscreen mode
Now, putting everything together, here’s the full code and the animated scatterplot:
<span>import</span> <span>pandas</span> <span>as</span> <span>pd</span><span>import</span> <span>matplotlib.pyplot</span> <span>as</span> <span>plt</span><span>%</span><span>matplotlib</span> <span>inline</span><span>import</span> <span>seaborn</span> <span>as</span> <span>sns</span><span>import</span> <span>imageio</span><span>import</span> <span>os</span><span>images</span> <span>=</span> <span>[]</span><span>folder</span><span>=</span><span>'</span><span>/home/lorena/Documents/bootcamp/W1/images</span><span>'</span><span>if</span> <span>not</span> <span>os</span><span>.</span><span>path</span><span>.</span><span>exists</span><span>(</span><span>folder</span><span>):</span><span>os</span><span>.</span><span>mkdir</span><span>(</span><span>folder</span><span>)</span><span>for</span> <span>year</span> <span>in</span> <span>range</span><span>(</span><span>1960</span><span>,</span> <span>2016</span><span>):</span><span>plt</span><span>.</span><span>axis</span><span>((</span><span>0</span><span>,</span> <span>100</span><span>,</span> <span>0</span><span>,</span> <span>10</span><span>))</span><span>sns</span><span>.</span><span>scatterplot</span><span>(</span><span>x</span><span>=</span><span>'</span><span>life_expectancy</span><span>'</span><span>,</span><span>y</span><span>=</span><span>'</span><span>fertility_rate</span><span>'</span><span>,</span><span>hue</span><span>=</span><span>'</span><span>continent</span><span>'</span><span>,</span><span>size</span><span>=</span><span>'</span><span>population</span><span>'</span><span>,</span><span>sizes</span><span>=</span><span>(</span><span>10</span><span>,</span> <span>1000</span><span>),</span><span>legend</span><span>=</span><span>False</span><span>,</span><span>data</span><span>=</span><span>gapminder_df</span><span>.</span><span>loc</span><span>[</span><span>gapminder_df</span><span>[</span><span>'</span><span>year</span><span>'</span><span>]</span><span>==</span><span>year</span><span>],</span><span>alpha</span><span>=</span><span>0.7</span><span>,</span><span>palette</span><span>=</span><span>'</span><span>Set2</span><span>'</span><span>)</span><span>plt</span><span>.</span><span>title</span><span>(</span><span>f</span><span>'</span><span>{</span><span>year</span><span>}</span><span>'</span><span>,</span> <span>loc</span><span>=</span><span>'</span><span>center</span><span>'</span><span>,</span> <span>fontsize</span><span>=</span><span>20</span><span>,</span> <span>color</span><span>=</span><span>'</span><span>black</span><span>'</span><span>,</span> <span>fontweight</span><span>=</span><span>'</span><span>bold</span><span>'</span><span>)</span><span>#plt.title(f'inspired by Hans Rosling', loc='right', fontsize=10, color='grey', style='italic', pad=-20) </span><span>#plt.legend(bbox_to_anchor=(0.74, 0.85), loc='center') </span><span>plt</span><span>.</span><span>xlabel</span><span>(</span><span>'</span><span>Life expectancy</span><span>'</span><span>)</span><span>plt</span><span>.</span><span>ylabel</span><span>(</span><span>'</span><span>Fertility rate</span><span>'</span><span>)</span><span>#plt.annotate({country}, ) </span><span>filename</span> <span>=</span> <span>f</span><span>'</span><span>lifeexp_</span><span>{</span><span>year</span><span>}</span><span>.png</span><span>'</span><span>plt</span><span>.</span><span>savefig</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>))</span><span>images</span><span>.</span><span>append</span><span>(</span><span>imageio</span><span>.</span><span>imread</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>)))</span><span>plt</span><span>.</span><span>figure</span><span>()</span><span>imageio</span><span>.</span><span>mimsave</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>'</span><span>scatterplot.gif</span><span>'</span><span>),</span> <span>images</span><span>,</span> <span>fps</span><span>=</span><span>20</span><span>)</span><span>import</span> <span>pandas</span> <span>as</span> <span>pd</span> <span>import</span> <span>matplotlib.pyplot</span> <span>as</span> <span>plt</span> <span>%</span><span>matplotlib</span> <span>inline</span> <span>import</span> <span>seaborn</span> <span>as</span> <span>sns</span> <span>import</span> <span>imageio</span> <span>import</span> <span>os</span> <span>images</span> <span>=</span> <span>[]</span> <span>folder</span><span>=</span><span>'</span><span>/home/lorena/Documents/bootcamp/W1/images</span><span>'</span> <span>if</span> <span>not</span> <span>os</span><span>.</span><span>path</span><span>.</span><span>exists</span><span>(</span><span>folder</span><span>):</span> <span>os</span><span>.</span><span>mkdir</span><span>(</span><span>folder</span><span>)</span> <span>for</span> <span>year</span> <span>in</span> <span>range</span><span>(</span><span>1960</span><span>,</span> <span>2016</span><span>):</span> <span>plt</span><span>.</span><span>axis</span><span>((</span><span>0</span><span>,</span> <span>100</span><span>,</span> <span>0</span><span>,</span> <span>10</span><span>))</span> <span>sns</span><span>.</span><span>scatterplot</span><span>(</span><span>x</span><span>=</span><span>'</span><span>life_expectancy</span><span>'</span><span>,</span> <span>y</span><span>=</span><span>'</span><span>fertility_rate</span><span>'</span><span>,</span> <span>hue</span><span>=</span><span>'</span><span>continent</span><span>'</span><span>,</span> <span>size</span><span>=</span><span>'</span><span>population</span><span>'</span><span>,</span> <span>sizes</span><span>=</span><span>(</span><span>10</span><span>,</span> <span>1000</span><span>),</span> <span>legend</span><span>=</span><span>False</span><span>,</span> <span>data</span><span>=</span><span>gapminder_df</span><span>.</span><span>loc</span><span>[</span><span>gapminder_df</span><span>[</span><span>'</span><span>year</span><span>'</span><span>]</span><span>==</span><span>year</span><span>],</span> <span>alpha</span><span>=</span><span>0.7</span><span>,</span> <span>palette</span><span>=</span><span>'</span><span>Set2</span><span>'</span><span>)</span> <span>plt</span><span>.</span><span>title</span><span>(</span><span>f</span><span>'</span><span>{</span><span>year</span><span>}</span><span>'</span><span>,</span> <span>loc</span><span>=</span><span>'</span><span>center</span><span>'</span><span>,</span> <span>fontsize</span><span>=</span><span>20</span><span>,</span> <span>color</span><span>=</span><span>'</span><span>black</span><span>'</span><span>,</span> <span>fontweight</span><span>=</span><span>'</span><span>bold</span><span>'</span><span>)</span> <span>#plt.title(f'inspired by Hans Rosling', loc='right', fontsize=10, color='grey', style='italic', pad=-20) </span> <span>#plt.legend(bbox_to_anchor=(0.74, 0.85), loc='center') </span> <span>plt</span><span>.</span><span>xlabel</span><span>(</span><span>'</span><span>Life expectancy</span><span>'</span><span>)</span> <span>plt</span><span>.</span><span>ylabel</span><span>(</span><span>'</span><span>Fertility rate</span><span>'</span><span>)</span> <span>#plt.annotate({country}, ) </span> <span>filename</span> <span>=</span> <span>f</span><span>'</span><span>lifeexp_</span><span>{</span><span>year</span><span>}</span><span>.png</span><span>'</span> <span>plt</span><span>.</span><span>savefig</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>))</span> <span>images</span><span>.</span><span>append</span><span>(</span><span>imageio</span><span>.</span><span>imread</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>filename</span><span>)))</span> <span>plt</span><span>.</span><span>figure</span><span>()</span> <span>imageio</span><span>.</span><span>mimsave</span><span>(</span><span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>folder</span><span>,</span><span>'</span><span>scatterplot.gif</span><span>'</span><span>),</span> <span>images</span><span>,</span> <span>fps</span><span>=</span><span>20</span><span>)</span>import pandas as pd import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns import imageio import os images = [] folder='/home/lorena/Documents/bootcamp/W1/images' if not os.path.exists(folder): os.mkdir(folder) for year in range(1960, 2016): plt.axis((0, 100, 0, 10)) sns.scatterplot(x='life_expectancy', y='fertility_rate', hue='continent', size='population', sizes=(10, 1000), legend=False, data=gapminder_df.loc[gapminder_df['year']==year], alpha=0.7, palette='Set2') plt.title(f'{year}', loc='center', fontsize=20, color='black', fontweight='bold') #plt.title(f'inspired by Hans Rosling', loc='right', fontsize=10, color='grey', style='italic', pad=-20) #plt.legend(bbox_to_anchor=(0.74, 0.85), loc='center') plt.xlabel('Life expectancy') plt.ylabel('Fertility rate') #plt.annotate({country}, ) filename = f'lifeexp_{year}.png' plt.savefig(os.path.join(folder,filename)) images.append(imageio.imread(os.path.join(folder,filename))) plt.figure() imageio.mimsave(os.path.join(folder,'scatterplot.gif'), images, fps=20)
Enter fullscreen mode Exit fullscreen mode
原文链接:How to create animated scatterplots with seaborn and imageio
暂无评论内容