I am plotting data in a radar plot and adding two vertical lines to mark an event +/- the standard deviation of that event. I would really like to shade between these lines covering the whole of the y axis
. So far I have tried ax.fill_between
and ax.span
but I'm not having any luck. Does anyone know how to do this? Basic code below.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.spines import Spine
from matplotlib.projections.polar import PolarAxes
from matplotlib.projections import register_projection
from math import pi
data = [1, 5, 10, 11, 15]
data = np.asarray(data)
labels = [10, 20, 30, 40, 50]
event1 = 3
st_dev_event1 = 1
def _radar_factory(num_vars):
theta = 2*np.pi * np.linspace(0, 1-1./num_vars, num_vars)
theta += np.pi/2
def unit_poly_verts(theta):
x0, y0, r = [0.5] * 3
verts = [(r*np.cos(t) + x0, r*np.sin(t) + y0) for t in theta]
return verts
class RadarAxes(PolarAxes):
name = 'radar'
RESOLUTION = 1
def fill(self, *args, **kwargs):
closed = kwargs.pop('closed', True)
return super(RadarAxes, self).fill(closed=closed, *args, **kwargs)
def plot(self, *args, **kwargs):
lines = super(RadarAxes, self).plot(*args, **kwargs)
for line in lines:
self._close_line(line)
def _close_line(self, line):
x, y = line.get_data()
if x[0] != x[-1]:
x = np.concatenate((x, [x[0]]))
y = np.concatenate((y, [y[0]]))
line.set_data(x, y)
def set_varlabels(self, labels):
self.set_thetagrids(theta * 180/np.pi, labels)
def _gen_axes_patch(self):
verts = unit_poly_verts(theta)
return plt.Polygon(verts, closed=True, edgecolor='k')
def _gen_axes_spines(self):
spine_type = 'circle'
verts = unit_poly_verts(theta)
verts.append(verts[0])
path = Path(verts)
spine = Spine(self, spine_type, path)
spine.set_transform(self.transAxes)
return {'polar': spine}
register_projection(RadarAxes)
return theta
N = len(labels)
theta = _radar_factory(N)
fig = plt.figure()
plt.clf()
ax = fig.add_subplot(1, 1, 1, projection='radar')
ax.plot(theta+(data<0.0)*np.pi, np.abs(data), color='#660066')
ax.set_theta_offset(pi / 1)
ax.set_theta_direction(-1)
ax.set_rlabel_position(90)
ax.set_varlabels(labels)
for label in ax.get_xticklabels()[::2]:
label.set_visible(False)
plt.axvline(theta[event1], color='#660066', linewidth=2, linestyle='dashed')
plt.axvline(theta[event1+st_dev_event1], color='b', linewidth=0.8, linestyle='dashed')
plt.axvline(theta[event1-st_dev_event1], color='b', linewidth=0.8, linestyle='dashed')
plt.show()
fig.clf()
I used filling twice: first, between theta[event1]
and the left bound and second, between theta[event1]
and the right bound using the following. Using theta[event1+st_dev_event1]
and theta[event1-st_dev_event1]
as x1
and x2
was not filling the whole y-axis. Let me know if this is not what you wanted:
ax.fill_betweenx(data, x1=theta[event1+st_dev_event1], x2=theta[event1],color='lightgreen')
ax.fill_betweenx(data, x1=theta[event1-st_dev_event1], x2=theta[event1],color='lightgreen')
Output