GitHub | Blog | Qiita
R の Date
/ POSIXct
型を利用していて過去にハマったポイントを備忘録として整理しておく。
for
loop 内で Date
が numeric
になってしまう問題
現象
Date
vector
に対して for
loop でアクセスすると意図した結果にならない
for
loop 内で class attribute が欠落してしまうことが原因
1
2
3
4
5
|
dates <- c(as.Date("2020-05-01"), as.Date("2020-05-02"))
for (date in dates) {
print(date)
}
|
対策 1: list
に変換してからループする
1
2
3
|
for (date in as.list(dates)) {
print(date)
}
|
1
2
|
[1] "2020-05-01"
[1] "2020-05-02"
|
対策 2: インデックスでアクセスする
1
2
3
|
for (i in seq_along(dates)) {
print(dates[i])
}
|
1
2
|
[1] "2020-05-01"
[1] "2020-05-02"
|
POSIXct
から Date
への変換で日付がずれる問題
現象
1
2
|
td <- as.POSIXct("2020-05-01")
as.Date(td)
|
- これは
as.Date()
は元の POSIXct
のタイムゾーンを意識せず、デフォルトで UTC へ変換してしまうことが原因
as.POSIXct()
で作成した場合、デフォルトでシステムのタイムゾーンを利用する (この場合は、JST)
- そのため、JST から 9 時間分の差が発生する
- 以下の例を見れば、違いが良くわかる
1
2
|
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
2
|
[1] "2020-04-30"
[1] "2020-05-01"
|
対策 1: tz
を指定する
- 変換前と変換後のタイムゾーンを揃えることを意識しておけば良い
- タイムゾーンは、”Area/Locality” の形式で指定すべき
1
2
3
4
5
6
7
|
# 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")
|
対策 2: lubridate::as_date()
を利用する
lubridate::as_Date()
は、元の POSIXct
のタイムゾーンを保持して変換してくれる
1
2
|
td <- as.POSIXct("2020-05-01")
lubridate::as_date(td)
|
ミリ秒の丸め問題
現象
- 文字列から
POSIXct
を作成する際に、ミリ秒がずれる (切り捨てられる)
1
2
3
|
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
|
[1] "2020-05-01 00:00:00.122 JST"
|
対策 1: lubridate::ymd_hms()
を使う
1
2
|
options(digits.secs = 3)
lubridate::ymd_hms("2020-05-01 00:00:00.123", tz = "Asia/Tokyo")
|
1
|
[1] "2020-05-01 00:00:00.123 JST"
|
[番外] ミリ秒単位の経過時間を POSIXct
に変換する
1
2
3
|
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
|
[1] "2020-05-01 00:00:00.123"
|
lubridate::as_datetime()
でも同じようにずれるので、+0.0005 する
1
|
lubridate::as_datetime(msec/1000 + 0.0005, tz = "JST")
|
1
|
[1] "2020-05-01 00:00:00.123 JST"
|
セッション情報
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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
|