-1

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()
Bulat
  • 720
  • 7
  • 15
p.liz
  • 23
  • 6
  • 1
    You code when copy-pasted and run, throws indentation error. Indent properly for convenience of others – Sheldore Aug 15 '18 at 13:41
  • As it stands, the indentation still seems off – Reblochon Masque Aug 15 '18 at 14:36
  • Not sure what else I can do it runs without error when I copy and paste into Spyder(Python 3.6). – p.liz Aug 15 '18 at 14:39
  • Can you post a sample output? Or at least give more details on which region you want to fill? Your pentagon shape plot has five regions. Which one of these do you want to be filled? – Sheldore Aug 15 '18 at 14:46
  • Hi Bazingaa, I would like to fill between the two dotted blue lines to represent the fact that the dotted purple line is the mean data point but there is lots of variation. Thanks for you help. – p.liz Aug 15 '18 at 14:54
  • Alternatively can I make the purple line the full width of the standard deviations? – p.liz Aug 15 '18 at 14:57
  • Check the answer below if this is what you want – Sheldore Aug 15 '18 at 15:05

1 Answers1

0

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

enter image description here

Sheldore
  • 37,862
  • 7
  • 57
  • 71
  • Thanks, this is exactly what I wanted. I hadn't thought of trying to do that. Much appreciated and sorry for any misunderstandings. – p.liz Aug 15 '18 at 15:12