読者です 読者をやめる 読者になる 読者になる

lubridate 1.5.6を使ってみる

1.5.0 → 1.5.6なので大きな変更はないんですが、いくつか新しい機能追加があったので。

ceiling_date()のオプション追加

#390 ceiling_date gains new argument change_on_boundary to allow ceiling on boundary of date-time objects.

日付時刻型データを切り上げる関数ceiling_date()は、隔月の1日をどう扱うかで微妙な挙動をします。デフォルトだと、1日は切り上げられません。

library(lubridate)

ceiling_date(as.Date("2016-03-01"), unit = "month")
#> [1] "2016-03-01"
ceiling_date(as.Date("2016-03-02"), unit = "month")
#> [1] "2016-04-01"

これにchange_on_boundaryを付けると1日も切り上げられるようになります。

ceiling_date(as.Date("2016-03-01"), unit = "month", change_on_boundary = TRUE)
#> [1] "2016-04-01"

正直あんまりイケてる解決策な気はしませんが。。月ごとの集計とかの処理をするときは注意しましょう。

ちなみに、floor_date()の方にはこういう挙動のぶれはありません。

Cのパーサの改良

C parser can now produce a list of date-time components suitable for POSIXlt constructors.

これは内部的な変更? なぜNEWS.mdに載るのか謎。

lt引数の追加、fast_strptime()の返り値の型がPOSIXltに

parse_date_time2 and fast_strptime gain new lt argument to control type of output.

lt引数によって返り値の型が変わります。これをTRUEにするとPOSIXltに、FALSEにするとPOSIXctになります。これが追加されたのは、 fast_strptime()をbaseのstrptime()の挙動と合わせるためです。

この変更によって、dplyrとfast_strptime()を組み合わせて使ってる人はエラーに悩まされるかもしれません。POSIXltはデータ構造がリストになっているのでdplyrは対応していません。

d <- data.frame(x = sprintf("2016-03-%02d 00:00:00", 1:10), stringsAsFactors = FALSE)
d %>%
  mutate(timestamp_x = fast_strptime(x, format = "%Y-%m-%d %H:%M:%S"))
#> Error: `mutate` does not support `POSIXlt` results

明示的にlt=FALSEを指定するかparse_date_time2()を使ってPOSIXctにしましょう。

d %>%
  mutate(timestamp_x = fast_strptime(x, format = "%Y-%m-%d %H:%M:%S", lt = FALSE))
#>                      x timestamp_x
#> 1  2016-03-01 00:00:00  2016-03-01
#> 2  2016-03-02 00:00:00  2016-03-02
#> 3  2016-03-03 00:00:00  2016-03-03
#> 4  2016-03-04 00:00:00  2016-03-04
#> 5  2016-03-05 00:00:00  2016-03-05

date()

#373 New date and date<- additions to the year, month etc family of accessors.

date()という関数で、時刻型のデータの日付を抜き出したり変更したりできます。baseのdate()(今の時刻の文字列を返す関数)と名前がかぶるのには注意。

(t <- Sys.time())
#> [1] "Sat Apr 09 08:35:01 2016"

date(t)
#> [1] "2016-04-09"

date(t) <- "2015-04-01"
t
#> [1] "2015-04-01 08:34:57 JST"

make_datetime()

#365 New very fast datetime constructor make_datetime (dropin replacement of ISOdatetime).

すでにyear、month、dayが分かれたデータがあるときはこれが便利そうです。(ISOdatetime()の存在を知らずに毎回paste0()したものをパースしてたのはナイショです)

library(dplyr)
data.frame(year = 1999, month = 1, day = 1:5) %>%
  mutate(datetime = make_datetime(year, month, day))
#>    year month day   datetime
#> 1  1999     1   1 1999-01-01
#> 2  1999     1   2 1999-01-02
#> 3  1999     1   3 1999-01-03
#> 4  1999     1   4 1999-01-04
#> 5  1999     1   5 1999-01-05

force_tz()with_tz()がdata.frameを扱えるようになった

#344 force_tz and with_tz can handle data.frames component-wise.

data.frameの中に時刻型の列があったらまとめてtimezoneを変換してくれるようになったよ、と。あんまり速くはなさそうです。

d <- data.frame(t = Sys.time() + 1:5, value = 1:5)
d
#>                      t value
#> 1  2016-04-09 09:07:15     1
#> 2  2016-04-09 09:07:16     2
#> 3  2016-04-09 09:07:17     3
#> 4  2016-04-09 09:07:18     4
#> 5  2016-04-09 09:07:19     5

with_tz(d, "UTC")
#>                     t value
#> 1 2016-04-09 00:07:38     1
#> 2 2016-04-09 00:07:39     2
#> 3 2016-04-09 00:07:40     3
#> 4 2016-04-09 00:07:41     4
#> 5 2016-04-09 00:07:42     5

as_date()

#355 New as_date replacement of as.Date with more intuitive behavior with non-UTC timezones.

baseのas.Date()が怪しい動きをするのでつくられた関数らしいです。Issue読んだけどよく分かりませんでした。

hms()が負の値も扱えるようになった

#333 hms parsers now handle negative components.

その他

#391 ymd family of functions return Date object when tz argument is NULL (new default) and POSIXct otherwise.
#364 Remove epoch functions.
For consistency with base:strptime fast_strptime now returns POSIXlt object. That is, its lt argument defaults to TRUE.

感想

なんか全体的に複雑になっていってやだなという感想...