I am making a polar plot where the ticks are not uniformly distributed around the circle. There are a few very good Q&A pairs that deal with uniformly distributed answers, and they all use a divide up the circle approach. E.g. this.
I'd like to know if it's possible to use the transform that's baked into the label to rotate the text the way I'd like to put it.
I can sort of do this, but I can't work out how to anchor it properly. The code that is doing it is here:
for tick in plt.xticks()[1]:
tick._transform = tick._transform + mpl.transforms.Affine2D().rotate_deg_around(0, 0, 10)
which gives an output like this:
Whereas I'd like an output like this:
(from the above linked question)
Obviously I'd need a 90° rotation, not a 10° one, but 90° rotates it off the canvas.
Is this approach possible, or do I need to reassess my strategy?
The full code block is here:
import random
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
one_person = {
"Human": {
"Collaboration": 4,
"Growth Mindset": 3,
"Inclusion": 5,
"Project and Studio Life": 2,
},
"Tectonics": {
"Office Manual and Procedures": 3,
"Documentation Standards": 3,
"Site Stage Services": 2,
"External and Public Domain Works": 2,
"Structure": 3,
"Enclosure": 2,
"Waterproofing (int. and ext.)": 3,
"Interiors": 1,
"Structure and Services": 2,
},
"Technology": {
"Bluebeam": 2,
"Confluence": 3,
"Drawing on screens": 0,
"dRofus": 0,
"Excel": 2,
"Grasshopper": 1,
"InDesign": 2,
"Outlook": 2,
"Python": 5,
"Rhino": 1,
"Teams": 2,
"Timesheets and expenses": 3,
},
"Regenerative": {
"REgenerative Design": 3,
"Materials and Embodied Carbon practice": 1,
"Materials and Embodied Carbon analysis": 2,
"Energy": 3,
"Resilience": 1,
"Rating Systems": 2,
},
"Design": {
"Predesign - Briefing, Stakeholder Engagement & Establishing Project Values": 2,
"Predesign - Feasibility Studies And Strategic Organisational Planning": 3,
"Initiating Design": 2,
"Conserving Design": 3,
"Design Communication - Written": 2,
"Design Communication - Visual": 4,
"Design Communication - Verbal": 3,
},
"Connecting with country": {"Connecting with Country": 2},
}
colours = [
"b", # blue.
"g", # green.
"r", # red.
"c", # cyan.
"m", # magenta.
"y", # yellow.
"k", # black.
# "w", # white.
]
def draw_radar(data, colour_letters, person_name=""):
"""Draw the graph.
Based substanitally on this SO thread:
https://stackoverflow.com/questions/60563106/complex-polar-plot-in-matplotlib
"""
# not really sure why -1, but if you don't you get an empty segment
num_areas = len(data) - 1
running_total = 0
thetas = {}
for key, value in data.items():
this_area_num_points = len(value)
this_area_theta = ((2 * np.pi) / num_areas) / (this_area_num_points)
thetas[key] = []
for i in range(len(value)):
thetas[key].append((i * this_area_theta) + running_total)
running_total += (2 * np.pi) / num_areas
labels = []
for key, value in data.items():
for area, score in value.items():
labels.append(f"{score} {key}: {area}")
for name, theta_list in thetas.items():
individual_scores = list(data[name].values())
colour = random.choice(colour_letters)
if len(theta_list) > 1:
plt.polar(theta_list, individual_scores, c=colour, label=name)
elif len(theta_list) == 1:
plt.scatter(theta_list, individual_scores, c=colour, label=name)
plt.yticks(np.arange(-5, 5), [""] * 5 + list(range(5)))
plt.xticks(
np.concatenate(tuple(list(thetas.values()))),
labels,
transform_rotates_text=True,
)
for tick in plt.xticks()[1]:
tick._transform = tick._transform + mpl.transforms.Affine2D().rotate_deg_around(
0, 0, 10
)
if person_name:
plt.title = f"Competency for {person_name}"
plt.savefig("radar.png")
draw_radar(one_person, colours)