【R】とりあえず簡単にggpplot2で2軸目を書きたい時はsec.axis
数ヶ月に一回ググってる気がするので自分用にメモ。
問題
とりあえずggplot2でエクセル的な2軸プロット(左右に別のY軸があってグラフが重なってるやつ)を書きたい。
ググっても丁寧なブログはたくさん見つかるのだが、とりあえずどれやればいいの!となる。
ggplot2以外に追加的にパッケージとかも使いたくない。
解決策
sec.axis
をscale_y_continuous()
で使う。
# 適当な例 ggplot(data, aes(x=x,y=y, col=group)) + geom_line()+ scale_y_continuous(sec.axis=sec_axis(~.*10, name="y2")) #ココ!
解説
準備
標準装備airqualityのデータを例に使います。
# パッケージ library(tidyverse) # ggplot2含む # データロード data(airquality) # 時系列データにするためにDate変数を作成 airquality = airquality %>% # 元データに月と日はあり(MonthとDay)。年は適当に今年になる。 mutate(date = as.Date(paste(Month,Day,sep="-"), format="%m-%d"))
ステップ1:とりあえず描画
ワイドデータ(異なる変数がそれぞれの列で記録されているデータ)をそのまま描画する場合です。
ロングデータ(変数の値が一つの列に記録され、もう一つの列に変数名やカテゴリが記録されてるようなデータ)は後述。
まずとりあえずデータをそのまま描画すると以下のようになる。
ggplot(data=airquality, aes(x=date)) + geom_line(aes(y=Wind,col="Wind"))+ geom_line(aes(y=Temp,col="Temp"))
なんかちょっと離れてるので重ねたい、みたいなときありますよね。
ステップ2:スケールする
一方の変数に係数をかけたり足し引きしたりすることでスケールする。
このスケールは、使うデータによるので、ここは数字みながら試行錯誤する必要ありです。
今回はシンプルに2つ目の変数である温度(temp)の数値が高いのでいい感じの数を引いてます。
# トライ2 スケールする ggplot(data=airquality, aes(x=date)) + geom_line(aes(y=Wind,col="Wind"))+ geom_line(aes(y=Temp-70,col="Temp"))
ステップ3:2軸目を足す
ここが一番の肝。
scale_y_continousの中でsec.axisという引数を使う。
このときに、sec_axisという関数で、数値をスケールすることができる。
上で70引いているので、ここでは70を足すことで本来の数値を表示できる。
# トライ3 2軸目を足す ggplot(data=airquality, aes(x=date)) + geom_line(aes(y=Wind,col="Wind"))+ geom_line(aes(y=Temp-70,col="Temp"))+ scale_y_continuous(sec.axis = sec_axis(~.+70)) # 2軸目のY軸
ステップ4:2軸目のラベルを足す
2軸目がなんなのか表示する。
nameという引数で表示できるが、sec_axis関数の中でつかうこと!
カッコを見間違えてsec_axisの外、scale_y_continuousの引数としてnameを使うと、エラーが返されずに第1軸のラベルとして認識されてしまう。
2軸だと単位が異なる事が多いので、軸ラベルに単位を明示すると丁寧ですよね。
ggplot(data=airquality, aes(x=date)) + geom_line(aes(y=Wind,col="Wind"))+ geom_line(aes(y=Temp-70,col="Temp"))+ scale_y_continuous(sec.axis = sec_axis(~.+70, name="Temp (F)"), name="Wind (m2/s)" )
なんでこんな気温高いんだと思ったら華氏(F)だからでした。
さらに細かくカスタマイズしたりスケールを設定するには「ggplot 2軸」とかで検索するとたくさんひっかかるのですが、とりあえず2軸!じゃあsec.axis!というのを覚えるために書きました。
おまけ:ロングデータ
ggplotだとロングデータ使って、color引数とかでカテゴリを色分けすることとか多いんですが、その場合はデータに予めスケールをかけとくほうがいいかもです。
以下はロングデータとワイドデータの違い。今回はOzoneとSolar.Rは無視してます。
#ロングデータに変換 airquality_long = airquality %>% pivot_longer(cols=c(Temp,Wind),names_to = "variable",values_to = "value") # ロングデータ > head(airquality_long) # A tibble: 6 × 7 Ozone Solar.R Month Day date variable value <int> <int> <int> <int> <date> <chr> <dbl> 1 41 190 5 1 2022-05-01 Temp 67 2 41 190 5 1 2022-05-01 Wind 7.4 3 36 118 5 2 2022-05-02 Temp 72 4 36 118 5 2 2022-05-02 Wind 8 5 12 149 5 3 2022-05-03 Temp 74 6 12 149 5 3 2022-05-03 Wind 12.6 #ワイドデータ > head(airquality) Ozone Solar.R Wind Temp Month Day date 1 41 190 7.4 67 5 1 2022-05-01 2 36 118 8.0 72 5 2 2022-05-02 3 12 149 12.6 74 5 3 2022-05-03 4 18 313 11.5 62 5 4 2022-05-04 5 NA NA 14.3 56 5 5 2022-05-05 6 28 NA 14.9 66 5 6 2022-05-06
スケールした新しい変数を作成
airquality_long = airquality_long %>% # もしvariableがTempなら70引く mutate(value2 = ifelse(variable=="Temp",value-70,value))
通常のggplot2の文法で書く。このときvalueではなくvalue2をy変数にセットする。
2軸の書き方は上と全く同じです。
ggplot(data=airquality_long, aes(x=date,y=value2,col=variable)) + geom_line()+ scale_y_continuous(sec.axis = sec_axis(~.+70, name="Temp (F)"), name="Wind (m2/s)" )