I know this meme is 100 Internet years old, but when I read this awesome post from Little Miss Data, I knew what I had to do:

Ok, ok.  So there are a few problems with the GIF:

  1. Rick’s head isn’t exactly centered and doesn’t pivot in a fluid way
  2. It would probably be nicer if the labels were over their respective wedges.

In Little Miss Data’s post, she uses R code to first generate her charts, then save them to PNG files, then load those PNG files as background images to pre-created, animated GIFs.  Unfortunately, I could find no way in Python to replicate that behavior.  So, I cheated a little: in a loop, I created my chart, dropped the Rickster on top of it, and saved the image to disk.  With every loop iteration, I slightly rotated Rick.  Outside of my loop, I used the imageio package to load all the saved images into one animated GIF.  Here’s a look at my code:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
data = [['Give you up', 30],
        ['Let you down', 20],
        ['Run around \nand dessert you', 20],
        ['Make you cry', 15],
        ['Say goodbye', 10],
        ['Tell a lie \nand \nhurt you', 5]]

headers = ['thing', 'percentage']

df = pd.DataFrame(data, columns=headers)

[os.remove(f) for f in glob.glob('fig_*.png')]  # remove any images from previous runs
pngs = []

for i in np.arange(0, 10):
    fig, ax = plt.subplots()
    img = plt.imread('rr2.gif')
    img_w, img_h, x = img.shape
    df.plot.pie(y='percentage', labels=df.thing, figsize=(9, 9), legend=False,
                title='Things Rick Astley would never do', ax=ax)
    ax.set_ylabel('')
    fig_w, fig_h = fig.get_size_inches()*fig.dpi
    rr = ndimage.rotate(img, i*36)
    _ = ax.figure.figimage(rr, fig_w/2 - img_w/2, fig_h/2 - img_h/2, zorder=1)
    fig.savefig('fig_{0}.png'.format(i))
    pngs.append('fig_{0}.png'.format(i))
   
images = []
for png in pngs:
    img = imread(png)
    images.append(img)
mimsave('rr_final.gif', images)

The full code is available on my Github page.

As for fixing the problems I identified earlier, I’m sure that can be done with some smarter calculations in the figimage line and the labels should be able to be adjusted through appropriate calls to the ax object, but I’ll leave that to someone with more time on his hands…or not, as this is probably a dumb thing to spend your time on.

Anyway, there you go: rick rolling the matplotlib way!