Issue
I would like to generate a pie radar / spider chart in python with 14 separate categories or "pizza slices". Something similar to this example created in excel or this example created with ggplot2.
This plt example was useful (code below), however the observations for different categories are connected with lines rather than having their own separate sections ("pizza slices"). Any ideas how to do this is python?
import matplotlib.pyplot as plt
import pandas as pd
from math import pi
df = pd.DataFrame({
'group': ['A','B'],
'r1': [2, 23],
'r2': [5, 5],
'r3': [1, 9],
'r4': [1, 1],
'r5': [3, 6],
'r6': [0, 0],
'r7': [17, 53],
'r8': [29, 44],
'r9': [0,2],
'r10': [0, 2],
'r11': [0, 3],
'r12': [1, 2],
'r13': [0, 3],
'r14': [0, 0],
})
categories=list(df)[1:]
N = len(categories)
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]
fig = plt.figure(figsize=(6,6))
ax = plt.subplot(111, polar=True)
ax.set_theta_offset(pi / 2)
ax.set_theta_direction(-1)
plt.xticks(angles[:-1], categories)#, rotation=70)
# Draw ylabels
ax.set_rlabel_position(10)
plt.yticks([20,40,60,80,100], ["20","40","60","80","100"], color="black", size=8)
plt.ylim(0,100)
values=df.loc[0].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid', label="A")
ax.fill(angles, values, 'b', alpha=0.7)
values=df.loc[1].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid', label="B")
ax.fill(angles, values, 'r', alpha=0.1)
plt.legend(loc='upper right', bbox_to_anchor=(0, 0))
Solution
In a radar chart, usually the values are one point per tick on the circular ax, connected with lines that form a zigzag pattern. A polar bar plot might be closer to the desired chart.
A polar bar plot is similar to a usual bar plot, but bent over a circle.
To get the bars and the labels nicely between the grid lines, the theta positions can be moved by half the bar width. And minor ticks can be used to get the grid lines back on their original position.
For consistency, the code below also changes some calls to plt.
to ax.
.
import matplotlib.pyplot as plt
from matplotlib.ticker import FixedLocator
import pandas as pd
from math import pi
import numpy as np
df = pd.DataFrame({'group': ['A', 'B'], 'r1': [2, 23], 'r2': [5, 5], 'r3': [1, 9], 'r4': [1, 1], 'r5': [3, 6], 'r6': [0, 0], 'r7': [17, 53], 'r8': [29, 44], 'r9': [0, 2], 'r10': [0, 2], 'r11': [0, 3], 'r12': [1, 2], 'r13': [0, 3], 'r14': [0, 0], })
categories = list(df)[1:]
N = len(categories)
angles = np.linspace(0, 2 * pi, N, endpoint=False)
angles_mids = angles + (angles[1] / 2)
fig = plt.figure(figsize=(6, 6))
ax = plt.subplot(111, polar=True)
ax.set_theta_offset(pi / 2)
ax.set_theta_direction(-1)
ax.set_xticks(angles_mids)
ax.set_xticklabels(categories)
ax.xaxis.set_minor_locator(FixedLocator(angles))
# Draw ylabels
ax.set_rlabel_position(0)
ax.set_yticks([20, 40, 60, 80, 100])
ax.set_yticklabels(["20", "40", "60", "80", "100"], color="black", size=8)
ax.set_ylim(0, 100)
values0 = df.loc[0].drop('group').values
ax.bar(angles_mids, values0, width=angles[1] - angles[0],
facecolor='b', alpha=0.7, edgecolor='k', linewidth=1, label="A")
values1 = df.loc[1].drop('group').values
ax.bar(angles_mids, values1, bottom=values0, width=angles[1] - angles[0],
facecolor='r', alpha=0.7, edgecolor='k', linewidth=1, label="B")
ax.grid(True, axis='x', which='minor')
ax.grid(False, axis='x', which='major')
ax.grid(True, axis='y', which='major')
ax.legend(loc='upper left', bbox_to_anchor=(0.9, 1))
plt.show()
Answered By - JohanC
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.