準備
例として以下のような、dplyr::group_by
でグループ化したデータフレームを用意する。
library(dplyr)
library(magrittr)
library(ggplot2)
df <- data.frame(
x = rep(c(1, 2, 4), c(10, 1, 20)),
g = rep_len(c("a", "b"), 31)
)
df %<>% group_by(g)
table(df)
## g
## x a b
## 1 5 5
## 2 1 0
## 4 10 10
そのままプロットするとこんな感じになって、特におかしなところはない。
# プロットできる
ggplot(df, aes(x = x)) +
geom_bar()
ところがこれにscale_y_log10
を使ってy軸を対数変換すると表示がおかしくなる。
# プロットできるがおかしい(なんか増えてね…?)
ggplot(df, aes(x = x)) +
geom_bar() +
scale_y_log10()
グループを見えるようにするとよく分かるが、対数変換した後に積んでいるので、y軸との対応が取れなくなっている。
# こういうこと(対数変換してから積んでる)
ggplot(df, aes(x = x, fill = g)) +
geom_bar() +
scale_y_log10()
それぞれのグループの変換自体は正しいので、position=dodge
を指定すれば矛盾のない表示になる。
# こうすれば良い
ggplot(df, aes(x = x, fill = g)) +
geom_bar(position = "dodge") +
scale_y_log10()
あるいはungroup
してしまってもよい。
# ungroupする
ggplot(ungroup(df), aes(x = x)) +
geom_bar() +
scale_y_log10()
ところでy軸を対数変換する別の方法として、scale_y_continuous
のtrans=
引数を使うものがあるが、このとき"log1p"
を指定すると、値に1を足した上で対数変換が行われる。こうすると1と0の区別ができるようになる。y軸の値ラベルはきちんと調整されるので、ずれることもない。
# プロットできる(1を消さない)
ggplot(ungroup(df), aes(x = x)) +
geom_bar() +
scale_y_continuous(trans = "log1p")
y軸を対数変換するさらに別の方法としてcoord_trans
を使うものがある。これはデータではなく軸の方を変換するためなのか、上記のデータはungroup
してもしなくてもプロットできない。
# プロットできない
ggplot(df, aes(x = x)) +
geom_bar() +
coord_trans(y = "log10")
# プロットできない
ggplot(ungroup(df), aes(x = x)) +
geom_bar() +
coord_trans(y = "log10")
一方、軸の方の変換なので、coord_trans
で"log1p"
を使えばposition="stack"
の状態でもy軸との関係を正しく保った状態でプロットができる(グラフとしてこれが適切なのかというと微妙だが)。
# プロットできる
ggplot(df, aes(x = x, fill = g)) +
geom_bar() +
coord_trans(y = "log1p")