RoKi
RoKi

Reputation: 41

Add gap between label and radar chart in matplotlib

I need a radar chart to visualize some key figures.

So I took the code from here and changed it a little bit, so it would fit my needs.

Here is the code that I use for my radar chart:

%matplotlib inline
import matplotlib.pyplot as plt
from math import pi

f = plt.figure(figsize=(10,5))

categories=['consistency', 'correctness', 'completeness']
N = len(categories)

values=[59,80,60]
values += values[:1]
values

angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]

ax = f.add_subplot(111, polar=True)

plt.xticks(angles[:-1], categories, color='grey', size=8)

ax.set_rlabel_position(180)
plt.yticks([20,40,60,80,100], ["20","40","60","80","100"], color="grey", size=10)
plt.ylim(0,100)

ax.plot(angles, values, 'o-', linewidth=1, linestyle='solid')

ax.fill(angles, values, 'b', alpha=0.1)

One thing I noticed, that the labels are way to close to the radar chart as you can see here, because they are longer than the labels that are used in examples of radar charts.

Upvotes: 2

Views: 1776

Answers (2)

The solution provided does not take direction and offset into account. In my radar chart I have an offset of pi/2, so that the first axis is at the top (rather than the right) and a direction of -1 (so the axes are positioned in clockwise direction, instead of the default counterclockwise)

    # If you want the first axis to be on top:
    ax.set_theta_offset(pi / 2)
    # If you want labels to go clockwise (counterclockwise is default)
    ax.set_theta_direction(direction='clockwise')

Anyway, I slightly modified your solution to include those as well:

    rstep = int(ax.get_theta_direction())
    if rstep > 0:
        rmin = 0
        rmax = len(angles)
    else:
        rmin = len(angles)-1
        rmax = -1

    for label, i in zip(ax.get_xticklabels(), range(rmin, rmax, rstep)):
        angle_rad = angles[i] + ax.get_theta_offset()
        if angle_rad <= pi / 2:
            ha = 'left'
            va = "bottom"
        elif pi / 2 < angle_rad <= pi:
            ha = 'right'
            va = "bottom"
        elif pi < angle_rad <= (3 * pi / 2):
            ha = 'right'
            va = "top"
        else:
            ha = 'left'
            va = "top"
        label.set_verticalalignment(va)
        label.set_horizontalalignment(ha)

Note that there was also a small error in the 'else:' bit in the answer. ha/va set to right/bottom where it should be left/top there. (Not noticeable with the example chart since it does not have a label in that quadrant).

Upvotes: 1

RoKi
RoKi

Reputation: 41

I found the solution in the post linked in the comment section.

Here is the changed code:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from math import pi

f = plt.figure(figsize=(8,4))

categories=['consistency', 'correctness', 'completeness']
N = len(categories)

values=[59,80,60]
values += values[:1]
values

angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]

ax = f.add_subplot(111, polar=True)

plt.xticks(angles[:-1], categories, color='grey', size=10)

for label,i in zip(ax.get_xticklabels(),range(0,len(angles))):

    angle_rad=angles[i]
    if angle_rad <= pi/2:
        ha= 'left'
        va= "bottom"

    elif pi/2 < angle_rad <= pi:
        ha= 'right'
        va= "bottom"

    elif pi < angle_rad <= (3*pi/2):
        ha= 'right'
        va= "top"  

    else:
        ha= 'right'
        va= "bottom"

    label.set_verticalalignment(va)
    label.set_horizontalalignment(ha)

ax.set_rlabel_position(180)
plt.yticks([20,40,60,80,100], ["20","40","60","80","100"], color="grey", size=10)
plt.ylim(0,100)

ax.plot(angles, values, 'o-', linewidth=1, linestyle='solid')

ax.fill(angles, values, 'b', alpha=0.1)

As you can see here the labels are now positioned correctly.

Upvotes: 2

Related Questions