在庫や待ち行列plot・階段グラフ【R言語・小技】

先日紹介した小技を使って階段グラフをつくる。
例えば機械の台数の推移や在庫・待ち行列など、
どのくらいの長い期間、どんな状態だったのかを知りたいときに階段グラフは役に立つ。

先日の記事で毎日データが残っていない時の対処方法は表現したので、
時系列表現についてはそちらを参考にしてほしい。

#前提としてこんなデータがある



![sstt.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/d91f62b1-5393-59e7-996e-f7f2b866977f.png)

ある商品が消費された・購入した、というin out情報と、
その時に取り扱われた量が日付とともに入っている。
一日に何回も消費されたり、購入したりという記録が入っているので、
まず一日ごとに数値を合計してやる必要がある。
もちろん合計するのはin out別々に。

dayの内容はYYYYMMDDになっている。
YYYY-MM-DDであれば時刻変換にかけたらいいが、
この場合は数値として扱うほうが便利。
あとで数値として一致させて処理する。



まずデータ内の日付を並び替える

```r
day <- unique(df$day)
days <- sort(day)
df <- df[order(df$day),]
```

複数同じ日が入っていたが、daysというデータの中でユニークをとってきた。
これで重複していない日付データが作成できた。
ついでにorderで日付列について並べ替えを行った。

ここは先日の記事を見てもらいたい

```r
ct_seq <- seq(as.POSIXct("2017-11-30","%Y-%m-%d",tz="Japan"),as.POSIXct("2019-08-01","%Y-%m-%d",tz="Japan"),24*60*60)
seq_date <- as.character(ct_seq)
time <- paste0(substr(seq_date,1,4),substr(seq_date,6,7),substr(seq_date,9,10))
```

購入したものと、消費したもので分け、
日付ごとに合計値を計算する。

```r
in_factor <- df[df$in.out=="in",]

df_bind <- NULL
in_factor_tbl <- NULL
for(q in 1:length(days)){
  cal <- in_factor[days[q]==in_factor$day,]
  df_bind <- data.frame(day=days[q],val=sum(cal$stoc))
  in_factor_tbl <- rbind(in_factor_tbl,df_bind)
}

out_factor <- df[df$in.out=="out",]

df_bind <- NULL
out_factor_tbl <- NULL
for(q in 1:length(days)){
  cal <- out_factor[days[q]==out_factor$day,]
  df_bind <- data.frame(day=days[q],val=sum(cal$stoc))
  out_factor_tbl <- rbind(out_factor_tbl,df_bind)
}
```

これで各日付についての値を合計したデータが作成できた。
取り扱いの無かった日は0が記入されている。

ただ、もともとの日付には、全く商品に動きが無かった日や、
土日のようにそもそもデータが記入されていない時がある。
これを以下の処理で修正する。
詳しくは先日の記事を参照してほしい。

```r
ind<-c(1:length(seq_date))
plot_label<-data.frame(ind=ind,day=as.numeric(time))

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

現在の商品在庫数を数えると、
4万個あったとする。

```R
act_stc <- 40000
```

現在の在庫から、過去のin outを表現していく。
昨日購入したものは、一昨日にはなかったものだから、
現状の在庫から引いていかなければいけない。
昨日消費したものは、一昨日にはあったものだから、
現状の在庫に足してやらなければいけない。

なので、過去にさかのぼるときは、inとoutの考え方を逆にして計算していく必要がある。


```r
in_val <- rev(in_factor_tbl$val)
out_val <- rev(out_factor_tbl$val)

stoc_move <- (in_val*-1) + (out_val)

stoc_trend <- as.numeric(act_stc)

for(cal in 1:length(days)){
  stoc_trend <- c(stoc_trend ,stoc_trend[cal] + stoc_move[cal])
}

stoc_trend <- rev(stoc_trend)
stoc_trend <- stoc_trend[-length(stoc_trend)]

get_ind$val <- stoc_trend

ytop <- rep(max(stoc_trend), length(seq_date)-1)
ybot <- c(ytop, min(stoc_trend))

plot(c(1:length(seq_date)), ybot, xaxt="n",type="n",xlab="",main="stoc trend",yaxt='n',ylab="")

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

```

これで欠損のある日付を考慮したplotができるようになった。
あとは階段グラフを描くために、segmentを使用して左右上下に線を描きだしてやる。

```r
for(seg in 1:(length(get_ind$ind)-1)){
  segments(get_ind$ind[seg], get_ind$val[seg], get_ind$ind[seg+1], get_ind$val[seg])
  segments(get_ind$ind[seg+1], get_ind$val[seg+1], get_ind$ind[seg+1] , get_ind$val[seg])
}
```


![stt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/2d0d63af-2db7-8a14-c6d2-9b80ef38a57b.png)

これで階段グラフが描けた

#以上
可視化大事に。