穴あき時系列plotのごまかし表現テクニック【R言語・小技】


#穴あきの時系列をplot

※データの予測モデルを作成する際の平均値埋めなどは出てきません

最近実務上で、

時系列データのうち、土日祝などの情報が欠けてしまっている。
でも、正確に土日などの感覚も認識したものをplotしたい。

ということがあり、使用したものを備忘録的に残す。



#例えばこんなデータがあるとして
想定として株価のデータにした。

![001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/ec6ed15a-0e94-144f-dfa8-3f08df979745.png)


データを確認すると、2010-12-17~2010-12-20の間の土日でデータが抜けている。
このような土日の欠損をすべて考慮して表現したい。

単純に土日を追加して0埋めしたとすると、

```r
plot(c(1:5),c(2000,2100,0,0,2000),type="l",xaxt="n",xlab="",ylab="")
```

![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/d9f81aa2-684c-5c30-44cb-0ac018d7a11b.png)


こんな図になる。
0に結び付けられてしまうので、このplotしたくない。

#そんなときは以下のようなデータの処理を行う

まず一列目を時刻変換する。

```r
time <- as.POSIXct(data[,1], "%Y-%m-%d", tz="Japan")
```

抜けている土日を正確に補填するために、
カレンダータイムを使って任意の時刻期間のデータを発生させる。
説明のしやすさを考え、便宜的に1年という期間を考える。

```r
ct_seq <- seq(as.POSIXct("2010-12-15","%Y-%m-%d",tz="Japan"), as.POSIXct("2011-12-14","%Y-%m-%d",tz="Japan"),24*60*60)
```

ct_seqには365行のデータが入っていることが想像できると思う。
このデータに1~length(ct_seq)までのindexをつける。

```r
ind <- c(1:length(ct_seq))
plot_label <- data.frame(ind=ind, day=ct_seq)
```

株価のデータは土日や祝日などが欠損している。
そもそも株式のデータ行数 = 株式市場の窓口の営業日数
なので、240日くらいだろう。

この240日の日付とplot_labelの日付を一致させ、
その一致した時のplot_labelのindexをとってくる。

```r
get_ind <- NULL

for(i in 1:length(time)){
  df_bind <- plot_label[plot_label$day == time[i],]
  get_ind <- rbind(get_ind, df_bind)
}

head(get_ind)
```

![rt.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/ed55eee1-ebb8-d27f-9db9-d98d9e87609f.png)


このget_indの行数は元データの240行数と一致する。
説明のためct_seqで発生させたデータは365日だった。
plot関数のx軸に1:365までを与えてやる。
get_indのind列に入っているのは土日を抜いた時のx軸の値として使用できる。

plot(c(1:365),・・・・)
x軸には1:365の値が入って
あとはpoints(get_ind$ind, data)
としてやれば、本来土日の値が入る場所には何もplotされず、
土日が空白であることが表現できる。


```r
plot(c(1:nrow(ct_seq)), c(rep(max(data$open),nrow(ct_seq)-1),min(data$open)), type="n")

points(get_ind$ind, data$open)
```

![333.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/0fa4e09d-bbe4-d175-cd5b-28b4980d63f5.png)

※便宜的に365として説明したが、plotに使用したのは2000行以上のデータだった。

#先ほどの先頭5つをplotで確認


```r
plot(c(1:nrow(ct_seq))[1:7], c(rep(max(data$open),nrow(ct_seq)-1),min(data$open))[1:7], type="n",ylim=c(min(data$open[1:5]), max(data$open[1:5])))

points(get_ind$ind[1:5], data$open[1:5],type="l")
```

![444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/0b98c23c-fea0-0fcd-cf64-92a77b9ad20a.png)

get_indには4と5は欠けているのでplotされず、軸には4,5を設定しているので土日が空いていることを正しく表現できている。

あとは余白の設定と、軸に日時情報を被せて、

```r

options(scipen=100)
par(mar=c(9,6,3,6))

plot(c(1:nrow(ct_seq))[1:7], c(rep(max(data$open),nrow(ct_seq)-1),min(data$open))[1:7], type="n",ylim=c(min(data$open[1:5]), max(data$open[1:5])), xlab="",ylab="",xaxt="n")
points(get_ind$ind[1:5], data$open[1:5],type="l")

axis(1,c(1:length(ct_seq)), labels=as.character(ct_seq),las=2)
axis(2)
axis(side=2,tck=1,lty="dotted")

```

![555.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/43133788-3f64-e9b5-5f69-2088f76ffb09.png)


これで土日を正確に表現しつつ、plotをかぶせることができた。


plotデータ中では実際にはx軸は日付ではなく数字で、
日付はあくまでもx軸のラベル名として入力している。
なのでabline(v=5)などと指定してやれば5日目に直線を引くことが出来る。

#これで土日を空白のままplotすることができた。



#以上

例えば空白の期間の長さを知りたい場合などにも使用できる。

機械の台数の変化や、在庫の移り変わり、待ち行列なども工夫次第で表現できる。

それはまた次の機会に。