LoginSignup
2
4

More than 3 years have passed since last update.

R の Date/POSIXct 型でハマったこと

Last updated at Posted at 2020-05-09

GitHub | Blog | Qiita

R の Date / POSIXct 型を利用していて過去にハマったポイントを備忘録として整理しておく。

for loop 内で Datenumeric になってしまう問題

現象

  • Date vector に対して for loop でアクセスすると意図した結果にならない
  • for loop 内で class attribute が欠落してしまうことが原因
dates <- c(as.Date("2020-05-01"), as.Date("2020-05-02"))

for (date in dates) {
  print(date)
}
[1] 18383
[1] 18384

対策 1: list に変換してからループする

for (date in as.list(dates)) {
  print(date)
}
[1] "2020-05-01"
[1] "2020-05-02"

対策 2: インデックスでアクセスする

for (i in seq_along(dates)) {
  print(dates[i])
}
[1] "2020-05-01"
[1] "2020-05-02"

POSIXct から Date への変換で日付がずれる問題

現象

td <- as.POSIXct("2020-05-01")
as.Date(td)
[1] "2020-04-30"
  • これは as.Date() は元の POSIXct のタイムゾーンを意識せず、デフォルトで UTC へ変換してしまうことが原因
    • as.POSIXct() で作成した場合、デフォルトでシステムのタイムゾーンを利用する (この場合は、JST)
    • そのため、JST から 9 時間分の差が発生する
  • 以下の例を見れば、違いが良くわかる
as.Date(as.POSIXct("2020-05-01 8:00:00")) # 2020-04-30 23:00 へ変換されてから、時間情報が削除されている
as.Date(as.POSIXct("2020-05-01 9:00:00")) # 2020-05-01 00:00 へ変換されてから、時間情報が削除されている
[1] "2020-04-30"
[1] "2020-05-01"

対策 1: tz を指定する

# UTC に統一して変換
td <- as.POSIXct("2020-05-01", tz = "UTC")
as.Date(td)

# もしくは、JST に統一して変換
## td <- as.POSIXct("2020-05-01")
## as.Date(td, tz = "Asia/Tokyo")
[1] "2020-05-01"

対策 2: lubridate::as_date() を利用する

  • lubridate::as_Date() は、元の POSIXct のタイムゾーンを保持して変換してくれる
td <- as.POSIXct("2020-05-01")
lubridate::as_date(td)
[1] "2020-05-01"

ミリ秒の丸め問題

現象

options(digits.secs = 3)
ms_dt <- as.POSIXct("2020-05-01 00:00:00.123", format = "%Y-%m-%d %H:%M:%OS")
ms_dt
[1] "2020-05-01 00:00:00.122 JST"

対策 1: lubridate::ymd_hms() を使う

options(digits.secs = 3)
lubridate::ymd_hms("2020-05-01 00:00:00.123", tz = "Asia/Tokyo")
[1] "2020-05-01 00:00:00.123 JST"

[番外] ミリ秒単位の経過時間を POSIXct に変換する

msec <- 1588291200123 # 2020-05-01 00:00:00.123 JST
dt <- as.POSIXct(msec/1000, origin = "1970-01-01", tz = "JST")
format(dt + 0.0005, "%Y-%m-%d %H:%M:%OS")
[1] "2020-05-01 00:00:00.123"
  • lubridate::as_datetime() でも同じようにずれるので、+0.0005 する
lubridate::as_datetime(msec/1000 + 0.0005, tz = "JST")
[1] "2020-05-01 00:00:00.123 JST"

セッション情報

sessionInfo()
R version 3.6.3 (2020-02-29)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.4 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=C
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=C
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
 [9] LC_ADDRESS=C               LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

loaded via a namespace (and not attached):
[1] compiler_3.6.3  generics_0.0.2  tools_3.6.3     Rcpp_1.0.4.6
[5] lubridate_1.7.8
2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4