獣医疫学メモ帳

獣医疫学(に関係ないかもしれない)メモ帳。

ggplot2のヒートマップで中間値を任意に指定する

目的

ggplot2でヒートマップを作るときに中間値1を任意に指定したい。
最終的に記事下部のやり方その2に着地。

このプロットで0を青、1を黄色、2000を赤にする。

library(ggplot2)
data <- faithfuld
data$z <- faithfuld$density * 50000

ggplot(data, aes(waiting, eruptions, fill = z)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", mid = "yellow", high = "red")

プロット中にも凡例にも青が見えない。

失敗例

最初はmidpointlimitを設定してやればいいだろ......と思っていたのだが実際やってみると以下の通り。青が見えない。

ggplot(data, aes(waiting, eruptions, fill = z)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", mid = "yellow", high = "red", midpoint = 1, limits = c(0, 2000))

成功例

その1:values = rescale(c(最小値, 中間値, 最大値))

やり方その1。scale_fill_gradientn()values = rescale(c(最小値, 中間値, 最大値))を設定する。

ggplot(data, aes(waiting, eruptions, fill = z)) +
  geom_tile() +
  scale_fill_gradientn(colours = c("blue", "yellow", "red"), values = rescale(c(0, 1, 2000)))

問題点

  • 青の部分がべったりしているのが気になる(対処可能:やり方2参照)。
  • legendに青が見えない。

その2:breaks/labels/limits = c(最小値, 中間値, 最大値)

やり方その2。scale_fill_gradientn()breakslabelslimitsc(最小値, 中間値, 最大値)を設定する。

ggplot(data, aes(waiting, eruptions, fill = z)) +
  geom_tile() +
  scale_fill_gradientn(colours = c("blue", "yellow", "red"), na.value = "blue",
                       breaks = c(1 / 2000, 1, 2000), labels = c(0, 1, 2000), limits = c(1 / 2000, 2000),
                       trans = "log")

今回は1をlegendの中央に持ってくるためにtrans = "log"を設定しているので最小値を1/2000にしているが、log変換しないのならば最小値は0でいい。
na.value = "最小値の色"の指定もlog変換しないなら不要。データ中にNAが存在する場合は、na.valueを指定する代わりにプロット前に最小値未満の値を最小値に置換しておく。

legendに青が見えるようになり、値が分かりやすくなった。

問題点?

  • やはり青がべったりしている。
    coloursbreaksの指定を増やすことで対処できるはず(試していない)だが今回は面倒くさいのでそこまでしていない。
  • legendの0の横が凹んでいる(分かりづらいだけで実は1の横も凹んでいる)。
    guide_colorbar()ticksまわりの設定で対処可能のはず(試していない)。

以上。


  1. 中央値ではない