読者です 読者をやめる 読者になる 読者になる

gap.plot()で省略される部分のラインを途中まで描く

plotrixパッケージに含まれるgap.plot()関数は、データの途中を省略したプロットを行う関数で、以前に少し紹介した。

このとき、typeに"o"、"l"、"b"などを指定した場合、省略範囲にかかるラインは描画されない。
f:id:Rion778:20141208233336p:plain
省略部分(まで|から)のラインも欲しい場合があるかもしれない。
要するに、こんなかんじの図である。
f:id:Rion778:20150113004548p:plain
上記の図を描くためにgap.plot()に少し小細工をしたものを用意した。

gap.plot.addline <- function(x, y, gap,
                             breakcol = "black",
                             breaklty = 1,
                             xlim = range(x), ylim = range(y),
                             xtics = NA, ytics = NA,
                             lty = rep(1, length(x)),
                             col = rep(par("col"), length(x)),
                             pch = rep(1, length(x)),
                             add = FALSE, stax = FALSE,
                             type = "p",
                             main = "", xlab = "x", ylab = "y")
    {
        ## まずgap.plotする
        gap.plot(x = x, y = y, gap = gap,
                 bgcol = "white", breakcol = "white", # 別途ablineで引く
                 xtics = xtics, ytics = ytics,
                 lty = lty,
                 col = col,
                 pch = pch,
                 add = add,
                 stax = stax,
                 type = type,
                 brw = 0,
                 main = main, xlab = xlab, ylab = ylab
                 )
        ## gap上下の値を計算
        lreg.idx <- max((1:length(y))[y < gap[1]]) # 下範囲の最大値のインデックス
        ureg.idx <- min((1:length(y))[y > gap[2]]) # 上範囲の最小値のインデックス
        lreg.x <- x[lreg.idx]; ureg.x <- x[ureg.idx] #x
        lreg.y <- y[lreg.idx]; ureg.y <- y[ureg.idx] #y
        ## 傾きを計算
        grad <- (ureg.y - lreg.y)/(ureg.x - lreg.x)
        ## 線引き
                                        # 下から境界まで
        lines(x = c(lreg.x,lreg.x + (gap[1] - lreg.y)/grad),
              y = c(lreg.y, gap[1]),
              col = col, lty = lty)
#             type = type,  pch = pch) # 特定のポイントを消す方法が欲しい…
                                        # 境界から上まで
        lines(x = c(ureg.x - (ureg.y - gap[2])/grad , ureg.x),
              y = c(gap[2], ureg.y) - diff(gap), # y軸の値からはgap分を差し引く必要がある
              col = col, lty = lty)              # gap.plotでadd=TRUEして追加した場合を除き、
#             type = type, pch = pch)            # y軸目盛りは下領域が延長されていると考えなければならない。
        ## 省略位置のラインは改めて引く
        abline(h = gap[1],
               col = breakcol,
               lty = breaklty)
    }

これをこのように使うとさっきの図が描ける。

gap.plot.addline(
    x, y, gap, breakcol = breakcol, breaklty = 2,
    ytics = ytics, type = type, col = col)
## 省略線をaxis.breakで記入しないと不自然
axis.break(5, axis = 2)
axis.break(5, axis = 4)

概ねもとのgap.plot()の感じで使えるが、多少制限がある。基本的には面倒だから制限になってしまっているだけなので、頑張ればきっとなんとかなる。

  • gapの指定は1カ所分しかできない(gap.plot()は2カ所)。
  • データは右肩上がりで省略範囲を通過すること。
  • 省略範囲を通過するのは1回だけであること(もとのgap.plot()も複数回省略範囲を通過するようなデータはうまくプロットできない)。
  • xの昇順でデータはソート済み(別に関数の中でソートするように修正すりゃいいのかもしれない)。
  • gapの厚み(brwで指定するもの)はゼロで固定(プロット範囲に対する相対値だったので、計算が面倒になってやめた)。
  • typeが"b"だと不自然(線の始点がポイントの中央なので重なってしまう)。

最後の点については、特定のポイントのみ描画なしにできれば解決できるんだけどそのような方法が見つからなかったので諦めた。これは頑張ってもだめかもしれない。
また、brwを0で固定している関係上、gap部分を線で示す必要性があろうかと思うので、ablineで別途指定できるようにもしてある。