質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Python 3.x

    6430questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Matplotlib

    312questions

    MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Pythonでレーダーチャートを書いたらレイアウトが崩れる

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 542

Uzura1994

score 11

 前提・実現したいこと

Python3系でレーダーチャートを作成したく
以下のサイトを参考に作成しておりました.
https://matplotlib.org/examples/api/radar_chart.html
https://teratail.com/questions/104066

しかしラベルをつけようとレイアウトが崩れてしまう問題が発生いたしました.

本来であれば下図になるものが
イメージ説明

私の結果は以下のようになってしまいます.

イメージ説明

コード

使用したコードは以下になります.
コピペコードですので元のサイトを一緒に掲載させていただきます.

まずhttps://matplotlib.org/examples/api/radar_chart.htmlより
実際にレーダーチャートを作成する関数をお借りしました.

def radar_factory(num_vars, frame='circle'):
    """Create a radar chart with `num_vars` axes.

    This function creates a RadarAxes projection and registers it.

    Parameters
    ----------
    num_vars : int
        Number of variables for radar chart.
    frame : {'circle' | 'polygon'}
        Shape of frame surrounding axes.

    """
    # calculate evenly-spaced axis angles
    theta = np.linspace(0, 2*np.pi, num_vars, endpoint=False)
    # rotate theta such that the first axis is at the top
    theta += np.pi/2

    def draw_poly_patch(self):
        verts = unit_poly_verts(theta)
        return plt.Polygon(verts, closed=True, edgecolor='k')

    def draw_circle_patch(self):
        # unit circle centered on (0.5, 0.5)
        return plt.Circle((0.5, 0.5), 0.5)

    patch_dict = {'polygon': draw_poly_patch, 'circle': draw_circle_patch}
    if frame not in patch_dict:
        raise ValueError('unknown value for `frame`: %s' % frame)

    class RadarAxes(PolarAxes):

        name = 'radar'
        # use 1 line segment to connect specified points
        RESOLUTION = 1
        # define draw_frame method
        draw_patch = patch_dict[frame]

        def fill(self, *args, **kwargs):
            """Override fill so that line is closed by default"""
            closed = kwargs.pop('closed', True)
            return super(RadarAxes, self).fill(closed=closed, *args, **kwargs)

        def plot(self, *args, **kwargs):
            """Override plot so that line is closed by default"""
            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()
            # FIXME: markers at x[0], y[0] get doubled-up
            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(np.degrees(theta), labels)

        def _gen_axes_patch(self):
            return self.draw_patch()

        def _gen_axes_spines(self):
            if frame == 'circle':
                return PolarAxes._gen_axes_spines(self)
            # The following is a hack to get the spines (i.e. the axes frame)
            # to draw correctly for a polygon frame.

            # spine_type must be 'left', 'right', 'top', 'bottom', or `circle`.
            spine_type = 'circle'
            verts = unit_poly_verts(theta)
            # close off polygon by repeating first vertex
            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


def unit_poly_verts(theta):
    """Return vertices of polygon for subplot axes.

    This polygon is circumscribed by a unit circle centered at (0.5, 0.5)
    """
    x0, y0, r = [0.5] * 3
    verts = [(r*np.cos(t) + x0, r*np.sin(t) + y0) for t in theta]
    return verts

その後,magichan様によるコード(掲載元→https://teratail.com/questions/104066)によって整形いたしました.

N = 9
theta = radar_factory(N, frame='polygon')

label= ['A','B','C','D','E','F','G','H','I']
data = [3.0, 0.00, 2.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00]

ax = plt.subplot(projection='radar')
# chartの範囲を0-3
ax.set_ylim(0, 3)
# Grid線を位置の指定
ax.set_rgrids([1, 2, 3])
# 描画処理
ax.plot(theta, data, 'c.-')
ax.fill(theta, data, facecolor='cyan', alpha=0.3)
ax.set_varlabels(label)
# 標準のグリッド線は円形なので消す(放射方向だけ残す)
ax.yaxis.grid(False)
# 替わりグリッド線を描く
ax.plot(theta, [1]*N, 'k-', marker=None, linewidth=0.5, alpha=0.3)
ax.plot(theta, [2]*N, 'k-', marker=None, linewidth=0.5, alpha=0.3)

plt.show()

やってみたこと

原因となっていそうなのが

ax.set_varlabels(label)


だと考えられます.
こちらをコメントアウトすると以下のようなレーダーチャートができます.

イメージ説明

考えられる可能性や解決方法がございましたら
ご教授いただきたいです.

初めて質問させていただいております.
不慣れな点もあるかと思いますが
どうかよろしくおねがいいたします.

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Uzura1994

    2018/06/14 19:14

    ご回答とご助言ありがとうございます.もう一度自身のコードを見直してみます!ありがとうございます.

    キャンセル

  • magichan

    2018/06/14 20:08

    リンク先の回答者です。私が書いたコードに関しては転載していただいても全く問題ありません。

    キャンセル

  • Uzura1994

    2018/06/14 21:21

    magichan様 ありがとうございます!質問の方編集させていただきます!

    キャンセル

回答 2

check解決した方法

0

怪しいところを片っ端からいじったらなんとかレーダーチャートになりました...

def radar_factoryの以下の部分をコメントアウトしたら解決しました.

#theta += np.pi/2

イメージ説明

しかしラベルの位置が0度のところから始まってしまっています....
でもデータとラベルがあってるのでまあ良しです!

ご回答にご協力いただきました皆様
ありがとうございました.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

自分の同じ箇所ではまっていたのですが、以下の処理を書き換えたら「theta += np.pi/2」をコメントアウトせず、90度回転(Aが上になるような表示)させることが出来ました。

def set_varlabels(self, labels):
            # 修正前
            # self.set_thetagrids(np.degrees(theta), labels)
            # 修正後
            self.set_thetagrids(np.degrees(theta)%360, labels)


おそらく、thetaに含まれている座標が360を超えるとレイアウトが崩れてしまっているような気がします。360度を超えている場合はあまりを出すように修正するとレイアウトが綺麗に表示されました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    6430questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Matplotlib

    312questions

    MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。