niszetの日記

細かい情報を載せていくブログ

(R) ggplot2パッケージでbode線図を描くための設定暫定版

あまり捻りがないですが…

これ

niszet.hatenablog.com

の続きです。

library(ggplot2)
library(magrittr)
library(sitools)


# define lpf function
lpf <- function(freq, R, C, ppd=20) {
  from_freq <- freq[1]
  to_freq <- freq[2]
  freq <- 10 ^ (seq(log10(from_freq), log10(to_freq), 1 / ppd))

  w <- 2 * pi * freq
  v <- 1 / (1i * w * C * R + 1)
  data.frame(list(x = freq, y = abs(v), s = atan2(Re(v), Im(v)) / pi * 180))
}
 

hogehoge_plot <- function(tmp, ycol, xlim=NULL) {
  
  breaks_x <- NULL
  minor_breaks_x <- NULL

  if (!missing(xlim)) {
    idx <- (floor(log10(xlim[1])) - 1):(ceiling(log10(xlim[2])) + 1)
    breaks_x <- 10 ^ idx
    minor_breaks_x <- rep(1:9, (idx[length(idx)] - idx[1] + 1)) * (10 ^ rep(idx, each = 9))
  }

  tmp %>% 
  ggplot(aes_(
      x = quote(x), y = ycol
    )) +
    geom_point() + geom_line() +
    (if(missing(xlim)) {scale_x_log10(labels = sitools::f2si )} else  {scale_x_log10(breaks = breaks_x, minor_breaks = minor_breaks_x, limits =  xlim, labels = sitools::f2si)}) +
      # 10のべき乗の書式が良ければ下記。しかし字が小さくて微妙。
      #breaks = trans_breaks("log10", function(x) 10 ^ x),
      #labels = trans_format("log10", math_format(10 ^ .x))
    scale_y_continuous(
      # 縦軸はどうするかね…
    ) +
    annotation_logticks(sides = "bt") + # size, short, long, mid について設定が出来るが、固定値だと厳しい…。
    theme(plot.title = element_text(size = 8), axis.title = element_text(size = 8)) +
    theme(
      panel.grid.major = element_line(size = 0.3, colour = "grey70"),
      panel.grid.minor.y = element_line(size = 0.1, color = "grey80", linetype = "solid"),
      panel.grid.minor.x = if (missing(xlim)) {
        element_blank()
      } else {
        element_line(size = 0.1, color = "grey80", linetype = "solid")
      },
      panel.background = element_rect(fill = "white", colour = "black")
    )+
    xlab("Frequency(Hz)") + 
    ylab("Magnitude")
}

# sample lpf object for bodeplot
tmp1 <- lpf(c(10, 1e9), R = 1000, C = 1e-9) # %>%

hogehoge_plot(tmp, ycol = quote(y), xlim=c(4e3, 6e8))

これの実行結果はこんな感じね。

f:id:niszet:20180327003032p:plain

grid周りが綺麗に描けると満足感ある。ただ、colorや、legendはまだ改良の余地がある。とりあえず暫定ではこんな感じかな。

missing(xlim)まわりはちょっと悩み中です。xlim与えないとminorのgridが表示されないとか、軸の目盛りの表示が荒くなるとかしてしまう。
いっそmissingしないで暫定値与えれば良いのでは?というのと、ggplot2パッケージは一体どのようにしてplot領域のmin-maxを決めているのかがわかればそれを使えると思うので、その辺りで改良していく予定。

あと、y軸がmagnitudeなのはlogじゃない軸を書いてみたかったからです。20log10か10log10されたものを表示させる前提でも良いかもしれない。complexで与えられる前提とか。
aesとNSEまわりも良く分からないのでもうちょっと調べないと…。軸に使う変数を与えるにはaesしかないと思うのだけども…。

あと、annotation_logticksはlog scaleになっていない軸に設定しようとすると、20GB(これは規模による)くらいのメモリを確保しに行ってコケます。どういう挙動なのか不明ですが、軸の設定をいじるときは注意で。あと、一部設定によっては引数群の末尾に,があっても動作してしまいますが、基本はNGだと思っていた方が良いです。無限に時間を溶かしました。

何気にxlimの前処理部分が個人的には便利で、breaksが中途半端な値を与えられるとgridが予期しない位置に出てくることを避けられます。もうちょっと良い方法があるかもしれないけど…

あとはcolorとかshape周りでscale_color_discreteとscale_shape_manualを外部から設定できるようにしたいなー…とか、titleとかthemeのまだ設定したことがない項目も触っていきたい。

これらの設定をデフォルトで持っているパッケージというかお便利関数が欲しいので作ろうかなーと思っている次第です。昔、geom_bodeってのを作ろうと思っていたのですが、geomにはthemeがないからダメだな…と思っていたけど、ggternを参考にやってみようと思います。

またもAtsushiさんに助けていただきました。ありがとうございます!

久々(?)の凄い乱文ですが、文章推敲する余裕がない…。いずれ更新します。

Enjoy!!