-1

Whilst plotting my complex radar chart, I am getting the error "radial grids must be strictly positive", but all of the values and ranges I have used in my radar chart are all positive. Can someone tell me why I am getting this error, and what I can do to fix it? The code I have used is below:-

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.8,0.8],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)

# example data
variables = ("Attribute1", "Attribute2", "Attribute3", 
            "Attribute4", "Attribute5", "Attribute6", "Attribute7",
             "Attribute8", "Attribute9", "Attribute10", "Attribute11",
             "Attribute12", "Attribute13", "Attribute14", "Attribute15",
             "Attribute16", "Attribute17")
data = (1.0, 185, 0.02, 
        1.5, 0.1, 1.3, 1.1,
        2.3, 0.1, 6.6, 24.5,
        83, 7.5, 5.6, 4.6,
        6.5, 1.3)
data2 = (1.0, 177, 0.0,
         0.0, 0.7, 1.3, 1.3,
         4.3, 0.0, 4.7, 30,
         93, 3.7, 5.0, 7.7,
         8.0, 3.5)
ranges = [(10.0, 0.0), (170.0, 189.0), (0.0, 0.3),
         (0.6, 5.2), (0.1, 2.0), (0.3, 2.2), (1.4, 0.3),
         (0.9, 3.0), (0.0, 0.7), (2.6, 11.4), (14.4, 43.5),
         (72.0, 94.0), (1.4, 7.9), (2.5, 6.5), (2.4, 6.2),
         (4.0, 7.9), (1.1, 3.9)]            
# plotting
fig1 = plt.figure(figsize=(9, 9))
radar = ComplexRadar(fig1, variables, ranges)
radar.plot(data, color="deepskyblue", label= "Compare1")
radar.fill(data, color="deepskyblue", alpha=0.5)
radar = ComplexRadar(fig1, variables, ranges)
radar.plot(data2, color="orangered", label= "Compare2")
radar.fill(data2, color="orangered", alpha=0.5)
radar.ax.legend(loc='upper center', bbox_to_anchor=(0.9, 1.10),
      fancybox=False, shadow=False, ncol=48)
plt.show()   
4

1 回答 1

1

嗨,这是学习一些调试技能的好时机。遇到这样的错误时,您要做的第一件事就是在代码中本地化它。幸运的是,python 通过回溯为您做到了这一点。这些回溯有时可能非常令人生畏,但仔细检查就会开始变得更有意义,并且可以提供非常有价值的信息。因此,让我们从错误的回溯开始。

回溯的前两个部分是:

ValueError                                Traceback (most recent call last)
<ipython-input-454-63a43ee81b1a> in <module>()
     91 # plotting
     92 fig1 = plt.figure(figsize=(9, 9))
---> 93 radar = ComplexRadar(fig1, variables, ranges)
     94 radar.plot(data, color="deepskyblue", label= "Compare1")
     95 radar.fill(data, color="deepskyblue", alpha=0.5)

<ipython-input-454-63a43ee81b1a> in __init__(self, fig, variables, ranges, n_ordinate_levels)
     54             gridlabel[0] = "" # clean up origin
     55             ax.set_rgrids(grid, labels=gridlabel,
---> 56                          angle=angles[i])
     57             #ax.spines["polar"].set_visible(False)
     58             ax.set_ylim(*ranges[i])

所以我们可以看到问题出ax.set_rgrids在 ComplexRadar__init__方法中。所以我们知道我们传递的参数会出现问题,要么grid要么angles。为了获得更多的想法,让我们看看错误消息的最后一部分:

/home/ianhi/anaconda/lib/python2.7/site-packages/matplotlib/projections/polar.pyc in set_rgrids(self, radii, labels, angle, fmt, **kwargs)
    565         rmin = radii.min()
    566         if rmin &lt;= 0:
--> 567             raise ValueError('radial grids must be strictly positive')
    568 
    569         self.set_yticks(radii)

ValueError: radial grids must be strictly positive

if rmin <= 0:因此,我们可以从那里得到“严格肯定”。虽然您传递的径向值都不是负数,但其中一些可能不大于 0。对于像这样的短代码,一种简单的调查方法是在违规行之前添加一个 print 语句。

print(grid)
ax.set_rgrids(grid, labels=gridlabel,
             angle=angles[i])

这样做我发现 grid = [ 0. 2. 4. 6. 8. 10.]. 啊哈!这包含一个 0。您必须选择从哪里开始网格。

出于测试目的,我使用了快速而肮脏的修复方法grid[0]=.01,结果发现第二个radar.plot 命令也抛出了错误!

这给了我们一个相当神秘的空白AssertionError

AssertionError                            Traceback (most recent call last)
<ipython-input-458-2a30b515f0d9> in <module>()
     96 radar.fill(data, color="deepskyblue", alpha=0.5)
     97 radar = ComplexRadar(fig1, variables, ranges)
---> 98 radar.plot(data2, color="orangered", label= "Compare2")
     99 radar.fill(data2, color="orangered", alpha=0.5)
    100 radar.ax.legend(loc='upper center', bbox_to_anchor=(0.9, 1.10),

<ipython-input-458-2a30b515f0d9> in plot(self, data, *args, **kw)
     63         self.ax = axes[0]
     64     def plot(self, data, *args, **kw):
---> 65         sdata = _scale_data(data, self.ranges)
     66         self.ax.plot(self.angle, np.r_[sdata, sdata[0]], *args, **kw)
     67     def fill(self, data, *args, **kw):

&lt;ipython-input-458-2a30b515f0d9> in _scale_data(data, ranges)
     13     inverts if the scale is reversed"""
     14     for d, (y1, y2) in zip(data[1:], ranges[1:]):
---> 15         assert (y1 <= d <= y2) or (y2 <= d <= y1)
     16     x1, x2 = ranges[0]
     17     d = data[0]

AssertionError: 

没有描述问题的有用消息的原因是您的方法_scale_data实际上引发了此错误。这个断言语句告诉我们一些关于 d 相对于 y2 和 y1 的值。相反,它实际上告诉我们,我们对 d 的某些想法是不真实的。要弄清楚发生了什么,让我们将 assert 语句包围在 try except 块中:

try:
    assert (y1 <= d <= y2) or (y2 <= d <= y1)
except AssertionError:
    print(d,y1,y2)

给我们留下几个例子,其中 d 既不满足 or 条件:

 d     y1   y2

(0.0, 0.6, 5.2)
(4.3, 0.9, 3.0)
(7.7, 2.4, 6.2)
(8.0, 4.0, 7.9)
(0.0, 0.6, 5.2)
(4.3, 0.9, 3.0)
(7.7, 2.4, 6.2)
(8.0, 4.0, 7.9)

此 try except 语句以及在 ax.set_rgrids 命令之前的 grid[0]=.001 允许您的代码运行并给出下图。但是,您应该考虑更改数据集以避免出现 grid[0]=0 问题,并可能删除 assert 语句,或者在失败时更正数据。希望这会有所帮助,因此您下次可以更轻松地进行调试。

在此处输入图像描述

于 2016-07-08T16:52:47.487 回答