Adding Legend To A Radarchart In Python
I want to create a radarchart with legends for every plot that is created but until now it has been impossible. Then, you can see the code used to create the plot (thanks to anothe
Solution 1:
In case someone is interested, the code of the ComplexRadar
comes from here.
The ComplexRadar
class uses many axes and makes all of them invisible, so the best way to create a legend here, would be to create a new axes to put the legend in. For that we need the handles of the plotted lines, so we need to change the ComplexRadar.plot()
method to return the line. We then need to collect those lines in a list (call it lax
) and supply them to the new legend.
I did make some changes to the code to make it work in python 2.7 and also to make it more comprehensible to myself. Here is, what should work:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
def_scale_data(data, ranges):
"""scales data[1:] to ranges[0],
"""for d, (y1, y2) inzip(data[1:], ranges[1:]):
assert (y1 <= d <= y2) or (y2 <= d <= y1)
x1, x2 = ranges[0]
d = data[0]
sdata = [d]
for d, (y1, y2) inzip(data[1:], ranges[1:]):
sdata.append((d-y1) / (y2-y1)
* (x2 - x1) + x1)
return sdata
classComplexRadar():
def__init__(self, fig, variables, ranges,
n_ordinate_levels=6):
angles = np.arange(0, 360, 360./len(variables))
axes = [fig.add_axes([0.1,0.1,0.9,0.9],polar=True,
label = "axes{}".format(i))
for i inrange(len(variables))]
l, text = axes[0].set_thetagrids(angles,
labels=variables)
[txt.set_rotation(angle-90) for txt, angle
inzip(text, angles)]
for ax in axes[1:]:
ax.patch.set_visible(False)
ax.grid("off")
ax.xaxis.set_visible(False)
for i, ax inenumerate(axes):
grid = np.linspace(*ranges[i],
num=n_ordinate_levels)
gridlabel = ["{}".format(round(x,2))
for x in grid]
if ranges[i][0] > ranges[i][1]:
grid = grid[::-1] # hack to invert grid# gridlabels aren't reversed
gridlabel[0] = ""# clean up origin
ax.set_rgrids(grid, labels=gridlabel,
angle=angles[i])
#ax.spines["polar"].set_visible(False)
ax.set_ylim(*ranges[i])
# variables for plotting
self.angle = np.deg2rad(np.r_[angles, angles[0]])
self.ranges = ranges
self.ax = axes[0]
defplot(self, data, *args, **kw):
sdata = _scale_data(data, self.ranges)
l = self.ax.plot(self.angle, np.r_[sdata, sdata[0]], *args, **kw)
return l
deffill(self, data, *args, **kw):
sdata = _scale_data(data, self.ranges)
self.ax.fill(self.angle, np.r_[sdata, sdata[0]], *args, **kw)
index = ["Carl","Michael","Peter","Louis","Sarah", "Laura","Nicholas"]
df = pd.DataFrame({
"Spe": pd.Series([89, 83, 70, 60, 30, 49, 28]),
"Str": pd.Series([69, 53, 30, 20, 10, 29, 48]),
"Det": pd.Series([82, 44, 79, 39, 20, 10, 85]),
"Extr": pd.Series([59, 74, 29, 36, 18, 29, 18]),
"Int": pd.Series([63, 11, 20, 36, 97, 58, 91]),
"Est": pd.Series([12, 69, 89, 59, 19, 58, 98]),
"Ape": pd.Series([29, 13, 94, 30, 20, 10, 67]),
})
variables = [k[0] for k in df.iteritems()]
ranges = [(1.,100.),(1.,100.),(1.,100.),(1.,100.),(1.,100.),(1.,100.),(1.,100.)]
fig1 = plt.figure(figsize=(8, 8))
radar = ComplexRadar(fig1, variables, ranges)
lax = []
for i, name inenumerate(index):
data=df.iloc[i].values
l, = radar.plot(data, label=name)
lax.append(l)
radar.fill(data,alpha=0.2)
legendax = fig1.add_axes([0.8,0.8,0.1,.1])
legendax.legend(handles = lax, labels=index, loc=3, bbox_to_anchor=(0,0,1,1), bbox_transform=fig1.transFigure )
legendax.axis('off')
sns.plt.show()
producing the following plot
Post a Comment for "Adding Legend To A Radarchart In Python"