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

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

ただいまの
回答率

88.58%

総当たり的subplotに見やすいtitleをつけたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,478

murmur1975

score 34

 やりたいこと

総当たり的プロットをする際に、見やすいタイトルをつけたい。
下図の上下左右の青と橙のタイトル(dataX)のようなものをつけたいです。
イメージ説明

 やったこと

長くてすみません。

import numpy as np
import matplotlib.pyplot as plt

label = ['data A','data B','data C','data D']
N = len(label) # データ種の数
L = 20  # データ長

data = []
for k in range(N):
    data.append(np.random.normal(0, 1, (L,2)))

pos = (0.2, 0.45, 0.45, 0.2)  # 上下左右の位置

fig = plt.figure()
for i in range(N):
    for j in range(N):
        if i!=j:
            ax = plt.subplot(N, N, i*N+j+1)
            d1x = data[i][:,0]
            d1y = data[i][:,1]
            ax.scatter(d1x, d1y, s=5)
            d2x = data[j][:,0]
            d2y = data[j][:,1]
            ax.scatter(d2x, d2y, s=5)
            dx = np.hstack([d1x, d2x])
            dy = np.hstack([d1y, d2y])
            if i == 0:  # 上
                x = (max(dx)+min(dx))/2
                y = max(dy)+(max(dy)-min(dy))*pos[0]
                ax.text(x, y, '{}'.format(label[j]), ha='center', va='bottom',
                        weight='bold', color='w', backgroundcolor='C1')
            elif i == N-1:  # 下
                x = (max(dx)+min(dy))/2
                y = min(dy)-(max(dy)-min(dy))*pos[1]
                ax.text(x, y, '{}'.format(label[j]), ha='center', va='top',
                        weight='bold', color='w', backgroundcolor='C1')
            if j == 0:  # 左
                x = min(dx)-(max(dx)-min(dx))*pos[2]
                y = (max(dy)+min(dy))/2
                ax.text(x, y, '{}'.format(label[i]), ha='right', va='center',
                        weight='bold', color='w', backgroundcolor='C0', rotation='vertical')
            elif j == N-1:  # 右
                x = max(dx)+(max(dx)-min(dx))*pos[3]
                y = (max(dy)+min(dy))/2
                ax.text(x, y, '{}'.format(label[i]), ha='left', va='center',
                        weight='bold', color='w', backgroundcolor='C0', rotation='vertical')
plt.tight_layout()
fig.subplots_adjust(top=0.9, bottom=0.1, left=0.1, right=0.9)

 困っていること

  1. グラフ表示後にマウスで拡大したり動かしたりすると、titleも連動して動いてしまう。
  2. グラフ要素が増えたりすると、再度細かい調整が必要になってしまう。
  3. そもそもなんかスマートじゃない。たぶん将来的に不具合が出る。

 教えてほしいこと

  1. このようなラベル付けができるモジュールがあれば、教えてください。
  2. もっとよい書き方があれば、教えてください。

以上、よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

単純に xlabel および ylabel にて実装するというのはどうでしょうか

import numpy as np
import matplotlib.pyplot as plt

label = ['data A','data B','data C','data D']
N = len(label) # データ種の数
L = 20  # データ長
data = []
for k in range(N):
    data.append(np.random.normal(0, 1, (L,2)))

#X軸とY軸を共通化する
fig,ax = plt.subplots(N, N, sharex=True, sharey=True)

for i in range(N):
    for j in range(N):
        # tickを共通化したので全てのグラフを表示する
        if i != j:
            d1x = data[i][:,0]
            d1y = data[i][:,1]
            ax[i][j].scatter(d1x, d1y, s=5, c='orangered')
            d2x = data[j][:,0]
            d2y = data[j][:,1]
            ax[i][j].scatter(d2x, d2y, s=5, c='royalblue')
        else:
            #ax[i][j].set_visible(False) #表示しない
            d1x = data[i][:,0]
            d1y = data[i][:,1]
            ax[i][j].scatter(d1x, d1y, s=5, c='fuchsia')

        # xlabelの設定
        ax[i][j].set_xlabel(label[j], weight='bold',
                            color='w', backgroundcolor='royalblue')
        # xlabelの表示場所を設定
        if i==0:
            ax[i][j].xaxis.set_label_position('top')
            ax[i][j].xaxis.labelpad = 15
        elif i==N-1:
            ax[i][j].xaxis.set_label_position('bottom')
        else:
            ax[i][j].xaxis.set_visible(False)

        # ylabelの設定
        ax[i][j].set_ylabel(label[i], weight='bold',
                            color='w', backgroundcolor='orangered')
        # ylabelの表示場所を設定
        if j==0:
            ax[i][j].yaxis.set_label_position('left')
        elif j==N-1:
            ax[i][j].yaxis.set_label_position('right')
            ax[i][j].yaxis.labelpad = 15
        else:
            ax[i][j].yaxis.set_visible(False)

        # これは完全に好み(上限下限を対象にしたかっただけ)
        ax[i][j].set_xlim(-3.0, 3.0)
        ax[i][j].set_ylim(-3.0, 3.0)

# 全てのグラフをくっ付けてみました(これも完全好み)
fig.subplots_adjust(top=0.9, bottom=0.1, left=0.1, right=0.9,
                    hspace=0, wspace=0)
plt.savefig('out.png')
plt.show()

もとのコードより長くなってしまった・・・

イメージ説明

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/26 15:01

    すごくいい感じですね。ありがとうございました。
    labelに設定する考えはあったのですが、どうにも上と右にlabelを設定する方法がわからず挫折してました。まだまだmatplotlib道は長そうです・・・。

    ただ実は、ほんとに使いたいコードでは、labelを別の用途に使ってしまっているので、こちらをベースにまた考えてみます。

    キャンセル

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

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

関連した質問

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