-
-
Save kylerbrown/29ce940165b22b8f25f4 to your computer and use it in GitHub Desktop.
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() |
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!
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 %")
Good morning
I am not getting to rotate the labels around the graph.:(
Could anyone help me please.
Thanks.
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.
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
@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 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!
@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.
@w-t-effi Thanks ! That solved my issue of not getting the axes inverted .
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!