ギャップのあるデータを途中を省略してプロットする

ギャップのあるデータ

例えばこのようなデータが有るとする。

testdata <- data.frame(x = 1:10,
                       y = c(1,3,2,4,3,21,23,22,24,23))

前半と後半の間にデータの大きな飛躍があるため、そのままプロットすると前半部、後半部の変化が相対的に小さくなって見難くなる。

## 通常のplot
plot(testdata, type = "b")

f:id:Rion778:20141208232141p:plain
実際そうなのだから別にこれで良かろうという意見もあろうかと思う。が、やむを得ない事情から中間部を省略しなければならないという状況に立たされる場合もあるかもしれない。きっとある。あるに違いない。

plotrixパッケージ

そのようなことをするためのツールを含め、なんか色々入ってるplotrixパッケージというものがある。

今回はこれを使ってデータを省略したプロットをやってみる。

install.packages("plotrix") #インストールして
library(plotrix)            #読み込む

gap.plot関数

途中を省略したいという要求はgap.plot関数を使えば叶う。

## gap.plot
gap.plot(testdata$x, testdata$y,        #dataframeはそのまま渡せない
         gap = c(5, 20),                #省略範囲を指定する必要がある
         ytics = 1:25,                  #ラベル位置は指定したほうが良い
         type = "b"                     #plotに指定できるオプションは大抵指定できる
         )

通常のplotと似たような使い方が出来るが、plotほど空気を読んでくれない部分もあるので引数は丁寧に指定したほうが良い。
xとyに対応するデータ、省略範囲の指定は必須である。
「gap.axis = "x"」を指定すればx軸の省略もできるが、両方一度に省略することはできない。
また、gapに4つの数値を指定すれば2つの範囲を一度に省略することができるが、3つ以上はできない。
ラベルは普通にやると適切に配置されないので指定したほうが良い。
結果はこうなる。
f:id:Rion778:20141208233336p:plain
このように、2つのグラフが隙間をあけて並べられたような形になる。他にもgap.boxplotやgap.barplotがあり、同様のプロットが簡単にできる。
「コレジャナイ…」という意見もあろうかとは思う。が、誤解を防ぐためにはギャップを明確に示したほうが良いというのが作者の意見の様である。ただし、このギャップ部分は色や大きさを調整できるので、見えないように調整することもできる。後述のaxis.breakと組み合わせると誤解を招きやすい感じにすることもできる。

axis.breakで軸に省略線を入れる

「『傾いた=みたいなので軸を省略してあるやつ』が欲しいんだよ」という意見があろうかと思う。この「傾いた=みたいなの」を入れるためだけの関数がaxis.breakである。
axis.breakに位置と目的の軸番号を指定するだけで記入できる。
これを、gap.plotの引数を調整してギャップ部分を見えなくしたグラフに組み合わせると、こんな感じになる。

## axis.breakと組み合わせる場合
gap.plot(testdata$x, testdata$y,
         gap = c(5, 20),
         brw = 0,                       #隙間はオプションで調整できる
         breakcol = "white",            #色も指定できる
         ytics = 1:25,
         type = "b"
         )
## 省略線をaxis.breakで記入する
axis.break(5, axis = 2)                 #位置と軸が必要
axis.break(5, axis = 4)

f:id:Rion778:20141208234446p:plain
これで、いかにも誤解を誘いそうだが一応言い訳はしてあるんだよという感じのグラフの完成である。
ちなみに、tyepに"l"や"b"を指定した場合、ギャップをまたぐ部分のラインは描画されない。これに関しては、傾きとギャップ部分の交点座標を求めるなどしてlines関数で別途対応すれば一応描ける。地味で面倒な作業なので今回は説明しない。