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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Matplotlib

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

Python 3.x

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

Q&A

解決済

2回答

4400閲覧

Python, Matplotlibでのヒートマップのカラーバーの中央値の変更

tsujitsuji

総合スコア13

Matplotlib

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

Python 3.x

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

0グッド

1クリップ

投稿2018/11/15 07:02

今回、ヒートマップを作成している中でカラーマップの中央値を変更できないのかと思い質問させていただきました。

python3

1import numpy as np 2import matplotlib.pyplot as plt 3 4heatmap = np.random.rand(10,10) 5 6plt.figure() 7plt.imshow(heatmap,vmin=0,vmax=1,cmap='coolwarm') 8plt.colorbar() 9plt.show()

というプログラムがあった際、カラーバーの中心(デフォルトでは0.5)を0.8に変更したいと考えております。
そのほかのヒートマップ作製可能なseabornでは'center = 0.8'と引数を与えることで中央値を指定できるのですが、matplotlib.pyplotでは指定の方法が分からず困っております。

現在、自分で色の変更(16進数で指定)することで対応をしているのですが、引き数やそのほかの方法で変更できないかと思い質問させていただきました。
お手数をおかけしますが、ご教授頂ければ幸いです。

よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2018/11/15 07:46

seabornでのコードおよび描画結果を追記くださると適切な回答が得られやすいと思います。またそのさい「np.random.seed(123)」などで乱数値を固定すると再現しやすいです。
guest

回答2

0

ベストアンサー

検索をかけたところ、SOに同様の質問がありました。
Stack Overflow - Change colorbar gradient in matplotlib

ImportanceOfBeingErnest氏のコードを借りると、勾配のあるマッピングができました。

Python

1import numpy as np 2import matplotlib 3import matplotlib.pyplot as plt 4 5class SqueezedNorm(matplotlib.colors.Normalize): 6 def __init__(self, vmin=None, vmax=None, mid=0, s1=2, s2=2, clip=False): 7 self.vmin = vmin # minimum value 8 self.mid = mid # middle value 9 self.vmax = vmax # maximum value 10 self.s1=s1; self.s2=s2 11 f = lambda x, zero,vmax,s: np.abs((x-zero)/(vmax-zero))**(1./s)*0.5 12 self.g = lambda x, zero,vmin,vmax, s1,s2: f(x,zero,vmax,s1)*(x>=zero) - \ 13 f(x,zero,vmin,s2)*(x<zero)+0.5 14 matplotlib.colors.Normalize.__init__(self, vmin, vmax, clip) 15 16 def __call__(self, value, clip=None): 17 r = self.g(value, self.mid,self.vmin,self.vmax, self.s1,self.s2) 18 return np.ma.masked_array(r) 19 20 21np.random.seed(123) 22data = np.random.rand(10,10) 23 24plt.figure() 25plt.imshow( 26 data, vmin=0, vmax=1, 27 cmap='coolwarm', norm=SqueezedNorm(vmin=0, vmax=1, mid=0.8) 28) 29 30plt.colorbar() 31plt.show()

実行結果
実行結果

クラスSqueezedNormについてはそのままコピって来たものなので、解説はできません。
というか私も良く分かってません。あくまで参考までに。

投稿2018/11/15 08:40

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tsujitsuji

2018/11/15 08:44

すごいです。 関数内の式や仕組みなどは理解できてないですが、これを使えば求めていたカラーマップになりそうです。 大変助かりました。 本当にありがとうございます。
LouiS0616

2018/11/15 08:47

当該回答はいわゆる神回答で、s1やs2やmidpointをスライダーでグイグイ変えて実験できるようなコードまで含まれています。すごすぎる。 いろんな値を試してみると良いでしょう。
tsujitsuji

2018/11/15 09:00

ありがとうございます。 こんなのができる方がいらっしゃるのがとんでもないです。 大学生でまだまだ知らないことも多く、またお世話になることがあるかもしれませんが、 その際にはよろしくお願いいたします。 プログラムについても解読ができるように頑張ってみます。
magichan

2018/11/15 09:23

なんか席を外している間にレスが凄いことに・・・。 SqueezedNorm 面白いですね。私も公式APIに CustomNormとか FunctionNorm みたいなものが探してみたのですが見つからなかったので colormap自体をカスタマイズするしかないかなと思っていたのですが、まさか colors.Normalize を自作している方がいるとは。 非常に有益な情報ありがとうございます。
guest

0

単純に 0.8 が中心になるように vmax=1.6 とするのでは駄目なのでしょうか?

Python

1import numpy as np 2import matplotlib.pyplot as plt 3 4heatmap = np.random.rand(10,10) 5plt.figure() 6plt.imshow(heatmap,vmin=0,vmax=1.6,cmap='coolwarm') 7plt.colorbar() 8plt.savefig('out.png') 9plt.show()

イメージ説明

投稿2018/11/15 07:13

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tsujitsuji

2018/11/15 07:17

ありがとうございます。 作成したいデータは色の相関を見るとともに、値についても重要なため 最大値、最小値は0, 1に固定したまま中央の灰色部分を0.8に持っていきたいです。 身勝手なのは重々承知ですがよろしくお願いいたします。
can110

2018/11/15 07:24

値と色の関係はどちらも変わらないので、私もこの案に賛成です。 カラーバーがなければどちらも見分けがつきません。
tsujitsuji

2018/11/15 07:34

質問の内容が分かりにくく申し訳ありません。 中央値を変更するにあたり、もう一つ変更するのが色の勾配です。 中央値を0.8に変更しますと、0から0.8までの色の変化が緩やかになり、逆に0.8から1までの変化が大きくなります。 そのような機能や補正の方法などがないかと思い質問させていただきました。
LouiS0616

2018/11/15 07:51 編集

@tsujitsuji さん sns.heatmap(data, vmin=0, vmax=1, center=0.8, cmap='coolwarm') で描いたヒートマップは、中央の位置は違えど色の勾配には変化が無いようなのですが。
tsujitsuji

2018/11/15 07:54

@LouiS0601さん ご連絡ありがとうございます。 申し訳ありません。私の思い違いでした。 ということは私の思っているように中央値を変更するのは厳しそうでということですね…
can110

2018/11/15 08:03

あ。もしかして一様乱数(rand)ではなく正規分布(randn)などの場合を想定されていますか?そうすると同じ結果を得るための最大、最小を求めるのは少し難しそうです。
tsujitsuji

2018/11/15 08:07

以前の質問に回答できておらず申し訳ありません。 そうです。実際には機械学習で予測した値を表にし、そのヒートマップを作成しようと考えております。 その際にある一定の値以上のところを注目させたく、その値を中央値にしたいと思って質問させていただきました。 ややこしくしてしまい申し訳ありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問