Skip to content

Instantly share code, notes, and snippets.

@kylerbrown
Last active May 2, 2024 12:07
Show Gist options
  • Save kylerbrown/29ce940165b22b8f25f4 to your computer and use it in GitHub Desktop.
Save kylerbrown/29ce940165b22b8f25f4 to your computer and use it in GitHub Desktop.
Code for a complex radar plot
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns # improves plot aesthetics
def _invert(x, limits):
"""inverts a value x on a scale from
limits[0] to limits[1]"""
return limits[1] - (x - limits[0])
def _scale_data(data, ranges):
"""scales data[1:] to ranges[0],
inverts if the scale is reversed"""
for d, (y1, y2) in zip(data[1:], ranges[1:]):
assert (y1 <= d <= y2) or (y2 <= d <= y1)
x1, x2 = ranges[0]
d = data[0]
if x1 > x2:
d = _invert(d, (x1, x2))
x1, x2 = x2, x1
sdata = [d]
for d, (y1, y2) in zip(data[1:], ranges[1:]):
if y1 > y2:
d = _invert(d, (y1, y2))
y1, y2 = y2, y1
sdata.append((d-y1) / (y2-y1)
* (x2 - x1) + x1)
return sdata
class ComplexRadar():
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 in range(len(variables))]
l, text = axes[0].set_thetagrids(angles,
labels=variables)
[txt.set_rotation(angle-90) for txt, angle
in zip(text, angles)]
for ax in axes[1:]:
ax.patch.set_visible(False)
ax.grid("off")
ax.xaxis.set_visible(False)
for i, ax in enumerate(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]
def plot(self, data, *args, **kw):
sdata = _scale_data(data, self.ranges)
self.ax.plot(self.angle, np.r_[sdata, sdata[0]], *args, **kw)
def fill(self, data, *args, **kw):
sdata = _scale_data(data, self.ranges)
self.ax.fill(self.angle, np.r_[sdata, sdata[0]], *args, **kw)
if __name__ == "__main__":
# example data
variables = ("Normal Scale", "Inverted Scale", "Inverted 2",
"Normal Scale 2", "Normal 3", "Normal 4 %", "Inverted 3 %")
data = (1.76, 1.1, 1.2,
4.4, 3.4, 86.8, 20)
ranges = [(0.1, 2.3), (1.5, 0.3), (1.3, 0.5),
(1.7, 4.5), (1.5, 3.7), (70, 87), (100, 10)]
# plotting
fig1 = plt.figure(figsize=(6, 6))
radar = ComplexRadar(fig1, variables, ranges)
radar.plot(data)
radar.fill(data, alpha=0.2)
plt.show()
@OD1995
Copy link

OD1995 commented Dec 7, 2017

Hi Kyler, I found this code from your post on Stack Exchange. I have been trying to recreate it but have run in to some problems.
When I run the whole script, Python keeps loading continuously and will not stop until I am forced to restart the terminal.
If I run the code line by line, no output is produced. Running "plt.show()" on the final line returns nothing, not even an error.
I'm not sure if this is helpful, but I am using Rodeo as my IDE and my matplotlib backend is TkAgg. Do you know what the problem might be? I am a fairly new user of Python so would hugely appreciate any suggestions, however obvious they may be! Thanks in advance!

@mopa
Copy link

mopa commented May 9, 2018

Hi! I try too this code but in my case IPython show me this error ValueError: figure size must be finite not (nan, nan) and <matplotlib.figure.Figure at 0x1b2449eddd8>.

In the IPython I write %matplotlib and I get Using matplotlib backend: Qt5Agg, and then afterwards run the code again, but IPython show me more errors.

I'd be very grateful if you'd help me. Regards!

@ericmagliarditi
Copy link

Question:

When I run the code, the labels on the plot block the view. How can I shift the labels on the plot so they do not impeded? The labels I am talking about are the variable names or ("Normal Scale", "Inverted Scale", "Inverted 2",
"Normal Scale 2", "Normal 3", "Normal 4 %", "Inverted 3 %")

@myjuda
Copy link

myjuda commented May 5, 2020

Good morning
I am not getting to rotate the labels around the graph.:(
Could anyone help me please.
Thanks.

@jsoutherland
Copy link

It looks like recent versions of matplotlib broke support for L39/40:

[txt.set_rotation(angle-90) for txt, angle in zip(text, angles)]

The labels are not rotating for me either.

@amarruedo797
Copy link

amarruedo797 commented Mar 1, 2021

Hi!
I have the same problem as @OD1995 , did you find a solution? The code works with non inverted ranges, but it gets stuck when inverting them.
Thanks

@jsoutherland
Copy link

@amarruedo797 I didn't find a solution yet, I just moved the labels outwards a bit so they didn't overlap for now:

        for txt, angle in zip(text, angles):
            # txt.set_rotation(angle-90) # TODO: doesn't work
            txt.set_position((-0.1,-0.1)) # move labels outward

@amarruedo797
Copy link

@amarruedo797 I didn't find a solution yet, I just moved the labels outwards a bit so they didn't overlap for now:

        for txt, angle in zip(text, angles):
            # txt.set_rotation(angle-90) # TODO: doesn't work
            txt.set_position((-0.1,-0.1)) # move labels outward

Hi! thanks for your answer,
in my case I can only get a graph when the ranges are not inversed, for example: (0,1), when I have a range : (1,0) the code does not work. I think it migth be an issue with the python and matplotlib versions? @kylerbrown, do you know if this could be the problem? Thanks!

@w-t-effi
Copy link

w-t-effi commented Nov 4, 2021

@amarruedo797 I had the same problem and for me, removing the lines 50 and 51 did the trick. I'm not 100% sure why that is the case, but I'm guessing newer matplotlib versions recognize when the ticks are reversed and do it automatically for the grid as well, so we're rereversing them with that line.

@sophont01
Copy link

@w-t-effi Thanks ! That solved my issue of not getting the axes inverted .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment