Radar Graph with Animation

This notebook walks through the plot of radar graph and network graph using matplotlib and networkx packages. It will also show how to make animations of radar graph to improve the visualization.

With the reference of Python Graph Gallery

Part 1. Radar Graph

Radar is useful when you try to compare multiple dimensions between multiple groups.

1.1 create a psedu dataframe

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from random import randint

group=['Group{}'.format(i) for i in range(1,11)]
strength =  [randint(1, 5) for p in range(0, 10)]
experience =  [randint(1, 5) for p in range(0, 10)]
emotion =  [randint(1, 5) for p in range(0, 10)]
language =  [randint(1, 5) for p in range(0, 10)]


Two ways to create a dictionary

  1. use dict()
pd.DataFrame(dict(Group = group,
                  Strength = strength,
                  Experience = experience,
                  Emotion = emotion,
                  Language = language),
             columns=['Group','Strength','Experience','Emotion','Language'])
Group Strength Experience Emotion Language
0 Group1 3 3 5 1
1 Group2 2 4 2 2
2 Group3 5 3 5 3
3 Group4 4 3 3 4
4 Group5 4 3 2 4
5 Group6 2 4 5 4
6 Group7 3 3 5 3
7 Group8 1 3 1 2
8 Group9 1 1 4 5
9 Group10 5 1 2 3
  1. Use zip
pd.DataFrame(dict(zip(['Group','Strength','Experience','Emotion','Language'],
                      [group,strength,experience,emotion,language])),
             columns=['Group','Strength','Experience','Emotion','Language'])
Group Strength Experience Emotion Language
0 Group1 3 3 5 1
1 Group2 2 4 2 2
2 Group3 5 3 5 3
3 Group4 4 3 3 4
4 Group5 4 3 2 4
5 Group6 2 4 5 4
6 Group7 3 3 5 3
7 Group8 1 3 1 2
8 Group9 1 1 4 5
9 Group10 5 1 2 3
performance = pd.DataFrame(dict(zip(['Group','Strength','Experience','Emotion','Language'],
                      [group,strength,experience,emotion,language])),
             columns=['Group','Strength','Experience','Emotion','Language'])

This performance dataframe records each group’s scores in four areas: strength, experience, emotion and language. Now we would like to visulization their differences in different areas. The best way to visualize is radar graph.

1.2 Draw Radar function

from math import pi
def drawRadar(df):
    plt.figure(figsize=(15,15))
    categories=list(df)[1:]
    N = len(categories)

    # What will be the angle of each axis in the plot? (we divide the plot / number of variable)
    angles = [n / float(N) * 2 * pi for n in range(N)]
    angles += angles[:1]

    # Initialise the spider plot
    ax = plt.subplot(111, polar=True)

    # If you want the first axis to be on top:
    ax.set_theta_offset(pi / 2)
    ax.set_theta_direction(-1)

    # Draw one axe per variable + add labels labels yet
    plt.xticks(angles[:-1], categories)

    # Draw ylabels
    ax.set_rlabel_position(0)
    plt.yticks([1,2,3,4,5], ["1","2","3","4","5"], color="grey", size=7)  ##where you should edit with different levels of y
    plt.ylim(0,5)   # set y limit


    # ------- PART 2: Add plots

    # Plot each individual = each line of the data
    # I don't do a loop, because plotting more than 3 groups makes the chart unreadable

    # Ind1
    for i in range(len(df)):
        values=df.loc[i].drop('Group').values.flatten().tolist()
        values += values[:1]
        ax.plot(angles, values, linewidth=0, label="group {}".format(i+1))
        ax.fill(angles, values, alpha=0.1)
drawRadar(performance)

png

As you can see, due to 20 groups, it is hard to compare better. We introduce animation of radar graph here.

1.3 Draw Radar function with animation

import matplotlib.animation as animation
fig = plt.figure(figsize=(15,15))
categories=list(performance)[1:]
N = len(categories)

# What will be the angle of each axis in the plot? (we divide the plot / number of variable)
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]

# Initialise the spider plot
ax = fig.add_subplot(111, projection='polar')

# If you want the first axis to be on top:
ax.set_theta_offset(pi / 2)
ax.set_theta_direction(-1)

# Draw one axe per variable + add labels labels yet
plt.xticks(angles[:-1], categories)

# Draw ylabels
ax.set_rlabel_position(0)
plt.yticks([1,2,3,4,5], ["1","2","3","4","5"], color="grey", size=7)
plt.ylim(0,5)

l,  = ax.plot([],[], linewidth=1, linestyle='solid')
ttl = ax.text(.5, 1.05, '', transform = ax.transAxes, va='center')
fill = ax.fill_between([], [],color='r')

#data=performance.iloc[0,:].values.flatten().tolist()
#data += data[:1]


def update(i):
    global data
    data=performance.iloc[i,:].drop('Group').values.flatten().tolist()
    data += data[:1]
    #data += (np.random.rand(50)+np.cos(i*2.*np.pi/50.))*2 
    #data[-1] = data[0]
    l.set_data(angles, data )
    ttl.set_text('group'+str(i))
    fill = ax.fill_between(angles,data)
    #fill.remove()
    #return l,
    return l, fill,

ani = animation.FuncAnimation(fig, update, frames=10, interval=1000, blit=True)
#plt.show()
plt.close()
from IPython.display import HTML
HTML(ani.to_jshtml())

</input>
Once </input> Loop </input> Reflect </input>