備忘ログ

チラシの裏的備忘録&メモ

Rのggplot2で軸の値を力技で任意の値に変えたい

タイトルの通り。やるときにちょっと調べることがあるのでメモしておく。下記はx軸のことをずっとやっているがy軸も似た要領でできるはず。ただy軸いじるのはEvilな例が多いと思う。

{ggplot2}で軸の値を力技で任意の値に変えたいと思った。本来は軸の値用のデータを持っておくのが良いと思うが、グラフを作ったあとに軸の値を変えたいと思った。いろいろな方法があると思うが、自分でやる用のメモをしておく。

適当なデータを作っておく。

set.seed(123)
df <- data.frame(x = 1:28,
                 y = rnorm(28, 100, 10))

これを{ggplot2}で適当なグラフを作ってみる。

library(ggplot2)
ggplot(df, aes(x = x, y = y)) +
  geom_line()

f:id:indenkun:20220215165945p:plain

このグラフのx軸が実は1980~2007年のデータだったとき、つまり、1が1980で30が2007になるとうれしい。

もちろん、軸用の値をもっているのがいいが、scale_x_continuous()をつかって置き換えることもできる。

ggplot(df, aes(x = x, y = y)) +
  geom_line() +
  scale_x_continuous(breaks = seq(1, 28, 9), labels = seq(1980, 2007, 9))

f:id:indenkun:20220215165957p:plain

置き換えられる値と置き換えたい値を指定するとうまくできる。

これは関数が勝手に作ってくれる{ggplot2}系のグラフをいじるときにつかえる。

例えば、{CausalImpact}で作られるグラフはggplotオブジェクトになっているので、

library(CausalImpact)
##  要求されたパッケージ bsts をロード中です

##  要求されたパッケージ BoomSpikeSlab をロード中です

##  要求されたパッケージ Boom をロード中です

##  要求されたパッケージ MASS をロード中です

## 
##  次のパッケージを付け加えます: 'Boom'

##  以下のオブジェクトは 'package:stats' からマスクされています: 
## 
##      rWishart

## 
##  次のパッケージを付け加えます: 'BoomSpikeSlab'

##  以下のオブジェクトは 'package:stats' からマスクされています: 
## 
##      knots

##  要求されたパッケージ zoo をロード中です

## 
##  次のパッケージを付け加えます: 'zoo'

##  以下のオブジェクトは 'package:base' からマスクされています: 
## 
##      as.Date, as.Date.numeric

##  要求されたパッケージ xts をロード中です

## 
##  次のパッケージを付け加えます: 'bsts'

##  以下のオブジェクトは 'package:BoomSpikeSlab' からマスクされています: 
## 
##      SuggestBurn
impact <- CausalImpact(df["y"], 
                       pre.period = c(1, 18),
                       post.period = c(19, 28))
plot(impact)

f:id:indenkun:20220215170008p:plain

で作られるもののx軸を任意の値(1を1980、28を2007)にしたいときに、

plot(impact) +
  scale_x_continuous(breaks = seq(1, 28, 9), labels = seq(1980, 2007, 9))

f:id:indenkun:20220215170018p:plain

とするとx軸を書き換えられる。{ggplot2}の機能を使っているのでオブジェクトがggplotなら汎用性があると思う。ただ注意しないと嘘っぱちグラフになってしまうかもしれない。

そもそも{CausalImpact}でx軸を任意の年にしたいのであればzooオブジェクトを作ってやれば素直にできるとおもう。

times <- seq.Date(as.Date("1980-01-01"), as.Date("2007-01-01"), by = "year")
df2 <- zoo(df, times)
impact <- CausalImpact(df2$y, 
                       pre.period = times[c(1, 18)],
                       post.period = times[c(19, 28)])
plot(impact) +
  scale_x_date(date_labels = "%Y")

f:id:indenkun:20220215170028p:plain

別に上記の例だとscale_x_date()で表記を年のみにしなくても良さそうではあるが、ちゃんと年だけ表示したいということを明示しておく。

{CausalImpact}の場合は上記のように日付つきのzooオブジェクトを作ってもよいとおもうが、(zoo使って日付割り振るのちょっとめんどくさいし)その他の関数でマニュアルよんでもよくわからんとなったときには簡単にやる方法を持っているのは一つの手段になると思う。