仕事で時系列データを触る機会があったので忘れないようメモ書き。
時系列のプロットしてる人少なくないですか?
探すのが下手なだけ?
だいたいデータを採取する計測器なり記録器なりで決まるので1パターンスクリプト書くと使いまわせる。
つまり、急に変な形の時刻データが来るとテンパる
今回はそんなデータ変換について出会ったパターンと、時刻のプロットについて記録しておきます。
データの変換
case1
一行目2019/01/01 二行目20:00:00 のとき。
綺麗に記録されているのでそのままas.POSIXctに通すと時刻データに変換される。
年月日には"/"だけでなく"-"が使われていても大丈夫。
case1 <- data.frame(day=c("2019/01/01","2019/01/01"),
time=c("20:00:00", "20:01:00"))
case1$ts <- as.POSIXct(paste(case1$day, case1$time))
case1$ts
# [1] "2019-01-01 20:00:00 JST" "2019-01-01 20:01:00 JST"
ちゃんと"JST"ついてますね。
case2
年月日に" "スペースや":"が使われているとき
そのままでは**「文字列は標準的な曖昧さのない書式にはなっていません」**とエラーが出てきてしまう。
こんな時は二つくらい解決法があります。
解決法1 置き換える gsub
case2_1 <- data.frame(day=c("2019:01:01","2019:01:01"),
time=c("20:00:00", "20:01:00"))
case2_1$day <- gsub(":", "-", case2_1$day)
case2_1$ts <- as.POSIXct(paste(case2_1$day, case2_1$time))
解決法2 フォーマットを指定する striptime
# 年が4文字表示2019の時は大文字Y 2文字19なら小文字y
case2_2 <- data.frame(day=c("2019:01:01","2019:01:01"),
time=c("20:00:00", "20:01:00"))
case2_2$day <- as.POSIXct(strptime(case2_2$day, "%Y:%m:%d"))
case2_2$ts <- as.POSIXct(paste(case2_2$day, case2_2$time))
case3
アメリカから渡されたデータとか、海外の機器データのとき。
表示がアメリカ式の月日年だし、年が2文字表示になっている。
さっき使ったformatを使います。format万能。
case3 <- data.frame(day=c("01-01-19","01-01-19"),
time=c("20:00:00", "20:01:00"))
# このままだと"0001-01-19 LMT"になってしまう
case3$day <- as.POSIXct(strptime(case3$day, "%m-%d-%y"))
case3$ts <- as.POSIXct(paste(case3$day, case3$time))
case4
年表示がアメリカだし、時間がスペース区切りになっている
フォーマットを指定する
分や秒は大文字H M S で指定してやる
case4 <- data.frame(day=c("01-01-19","01-01-19"),
time=c("20 00 00", "20 01 00"))
# 時間がスペース区切りだとtrimできないというエラーが出る
# とりあえず汚いままくっつけて
case4$day_and_time <- paste(case4$day, case4$time)
# "01-01-19 20 00 00" "01-01-19 20 01 00"
# すべてのフォーマットを指定 スペースで時刻が区切られていることを示しておく
case4$ts <- as.POSIXct(strptime(case4$day_and_time, "%m-%d-%y %H %M %S"))
でも私はよくformatのYとかHとか忘れるからあきらめて置き換えてしまうんですけどね
case4$time <- gsub(" ", ":", case4$time)
次に作図
こちらはいろいろコメントアウトで書き残しておきます。
# とりあえずサンプルデータの作成
sample <- NULL
sample$time <- seq(as.POSIXct("2010-07-31 00:00:00"),
as.POSIXct("2010-08-20 18:00:00"), by="5 min")
# byで指定すると日ごと(day)や時間(〇hours)など、指定した間隔ごとのデータを扱える。便利
# 時間に合うように乱数を発生。
sample$data <- rnorm(n=length(sample$time), mean=10,sd = 0.5)
# とりあえずプロット
# matplotでx軸に時間を、y軸に値を設定する
# プロットはせずに書き込む図面を作る。
# x軸はきれいにしておくxaxt, xlab
# pngにするならwidthとheightで調整すると見やすい。
y_limit<-c(5,15)
matplot(sample$time, sample$data,
type="n", lty=0, xaxt="n", xlab="",
las=1, ylim=y_limit, main="plot ts")
# 背景にグリッドを作成する
# x軸を時間にしておくと、グリッドも時刻発生の時と同じように、何時間刻みでほしいか指定できる
# 点線はlty=3
last <- length(sample$time)
abline(v=seq(as.POSIXct(sample$time[1]),
as.POSIXct(sample$time[last]),
"5 hours"),
lty=3, col="lightgray")
# 横へのグリッドもお好きに設定してください
abline(h=seq(0,30, 1), lty=3, col="lightgray")
matpoints(sample$time, sample$data, type="l", lty=1, col=rainbow(5))
# 軸を細かく設定
# 右側にもほしければ4を指定
axis(4, las=2)
# 下に軸が欲しいからside=1を設定
axis.POSIXct(side=1,
at=seq(as.POSIXct(sample$time[1]),
as.POSIXct(sample$time[last]),
"1 day"), las=2, format="%m/%d %H:%M")
# 分秒が不要ならseqの中身を月日だけに書き換えて作ればいい
次に特定の区間のデータだけ見たいときの指定方法
plot_start <- as.POSIXct("2010/08/01 09:00:00")
plot_end <- as.POSIXct("2010/08/01 18:00:00")
trim_time <- plot_start <= sample$time & sample$time <= plot_end
# 当てはまるデータに対してTorFが判断される
# これをmatplotの時に使えばいい
matplot(sample$time[trim_time], sample$data[trim_time])
また思い出したら書き足します。
locator関数について
20190419追記
切り取りたい区間のプロットについては上で紹介しました。
ですが、とりあえずプロットしてから区間を決めたいということもあるかと思います。
そんなときはlocator関数が便利。
座標を記録しておいてくれます。
# plotしてからlocator(記録させたい回数)
cut_loca <- locator(2)
cut_loca
# $`x`
# [1] 1282238549 1282193931
# $y
# [1] 10.1266 10.1266
x座標についてはとんでもない数字になっていますが、
おそらくこれはPOSIXが1970年?を0として計算しているからではないかと思われます。
もし切り取りたい座標をわかりやすくしたい場合、時間をx軸にするのではなく、
一度行番号をx軸に当てはめてからplotしてやれば、データの何行目かが取得できます。

