Rで時刻の差をとるときは単位を指定する癖をつける(もしくはlubridate::time_length()を用いる)
時刻を入れたデータフレームがあるとする。
> smp <- data.frame(now=Sys.time(), then=Sys.time()-60) > smp now then 1 2019-02-09 10:30:15 2019-02-09 10:29:15
で、時刻の差を計算すると、そこに単位も含まれてくる。
> smp$diff <- with(smp, now - then) > smp now then diff 1 2019-02-09 10:30:15 2019-02-09 10:29:15 59.99999 secs
これは煩わしいので、as.numeric()で数値に変える。
> smp$diff <- with(smp, as.numeric(now - then)) > smp now then diff 1 2019-02-09 10:30:15 2019-02-09 10:29:15 59.99999
一見問題ないように見えるが、次のような時に困る。
> smp <- data.frame(now=Sys.time(), then=Sys.time()-3600) > smp$diff <- with(smp, as.numeric(now - then)) > smp now then diff 1 2019-02-09 10:38:55 2019-02-09 09:38:55 60
これは時刻の差分を計算する時に呼び出されるdifftime()の引数unitsがデフォルトではautoとなっていることに起因する。 したがっていつも同じ単位で結果が欲しいときは、演算子ではなくdifftime()を用いて、unitsを指定するとよい。
> smp$diff <- with(smp, as.numeric(difftime(now, then, units = "secs"))) > smp now then diff 1 2019-02-09 10:45:00 2019-02-09 09:45:00 3600
もしくはlubridateパッケージでtime_length()を用いるという手もある。 こちらはデフォルトがsecsになっている。 なお、time_length()はIntervalクラスの値を求めるので、interval()してから渡してやる必要がある点に注意。
> smp$diff <- with(smp, time_length(interval(then, now))) > smp now then diff 1 2019-02-09 10:45:00 2019-02-09 09:45:00 3600
interval()の演算子として%--%も用意されているので、パイプを使いたいときはこちらもあり。
> smp <- smp %>% + mutate(diff = then %--% now %>% time_length()) > smp now then diff 1 2019-02-09 10:49:53 2019-02-09 09:49:53 3600
いかがでしたか????