INPUTしたらOUTPUT!

忘れっぽいんでメモっとく

lubridateパッケージによる日付型データの加工

以下の本をペラペラ見てたら日付データの加工にはlubridateパッケージが便利とのこと。
3年前に既に@dichika氏が紹介してたけど試してみる。

Data Manipulation With R

Data Manipulation With R

参考 → lubridateパッケージ大便利 - 盆栽日記


日付オブジェクトの作成

日付型オブジェクトの作成を組込みのas.Date(), lubridateパッケージの関数でそれぞれ作ってみる。

> # 標準のas.Date()を使用する場合
> as.Date("2015-06-17")
[1] "2015-06-17"

> as.Date("2015/06/17")
[1] "2015-06-17"

> as.Date("20150617", format="%Y%m%d")
[1] "2015-06-17"

> as.Date("17-06-2015", format="%d-%m-%Y")
[1] "2015-06-17"

> as.Date("06-17-2015", format="%m-%d-%Y")
[1] "2015-06-17"

> # lubridateパッケージのymd(), dmy(), mdy()を使うとformatの指定が不要。
> ymd("2015-06-17")
[1] "2015-06-17 UTC"

> ymd("2015/06/17")
[1] "2015-06-17 UTC"

> ymd("20150617")
[1] "2015-06-17 UTC"

> dmy("17-06-2015")
[1] "2015-06-17 UTC"

> mdy("06-17-2015")
[1] "2015-06-17 UTC"


冒頭の書籍には

One of the most interesting and important features of the lubridate package is that it can process date variables in heterogeneous formats. Heterogeneous formats means users can store date information in various ways:

とあり、ymd()などに日付っぽい文字列をぶち込むとparseして日付オブジェクトを返してくれるとのこと。
以下サンプル。

> # creating heterogeneous date object
> hetero_date <- c("second chapter due on 2013, august, 24",
+                  "first chapter submitted on 2013, 08, 18", 
+                  "2013 aug 23")

> # parsing the character date object and convert to valid date
> ymd(hetero_date)
[1] "2013-02-04 UTC" "2013-08-18 UTC" "2013-02-03 UTC"

ってaugust, augがparseできていない。。。
どうも自分の環境では月の略称・正称は上手く認識されないようだ。(ロケールなどを変更してみても上手くいかなかった)


> Sys.setlocale("LC_ALL", 'en_US.UTF-8')
[1] "en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8"
> Sys.setenv(LANG = "en_US.UTF-8")
> as.Date("Jun-17-2015", format="%b-%d-%Y")
[1] NA


(追記)対処法を教えて頂きました!

> ymd(hetero_date, locale="C", tz="Asia/Tokyo")
[1] "2013-08-24 JST" "2013-08-18 JST" "2013-08-23 JST"

parseできた!


時刻オブジェクトの作成

同様にas.POSIXct()とlubridateパッケージの関数でそれぞれ作成してみる。

> as.POSIXct("17-06-2015 12:34:56",format = "%d-%m-%Y %H:%M:%S")
[1] "2015-06-17 12:34:56 JST"
 
> dmy_hms("17-06-2015 12:34:56")
[1] "2015-06-17 12:34:56 UTC"


lubridateパッケージの関数はタイムゾーンがデフォルトでUTCとなる。
tzオプションでタイムゾーンを指定できるが"JST"を指定すると"GMT"になってしまう。

> dmy_hms("17-06-2015 12:34:56",tz="JST")
[1] "2015-06-17 12:34:56 GMT"
Warning messages:
1: In as.POSIXct.POSIXlt(lt) : unknown timezone 'JST'
2: In as.POSIXlt.POSIXct(ct) : unknown timezone 'JST'
3: In as.POSIXct.POSIXlt(t) : unknown timezone 'JST'
4: In as.POSIXlt.POSIXct(ct) : unknown timezone 'JST'
5: In as.POSIXlt.POSIXct(x, tz) : unknown timezone 'JST'


(追記) 対処法教えて頂きました!ありがとうございます!!

> dmy_hms("17-06-2015 12:34:56",tz="Asia/Tokyo")
[1] "2015-06-17 12:34:56 JST"

JSTになった!


現在の日付、時刻の取得

現在日時の取得も直感的に行なえる。

> # 標準の関数で取得
> date()
[1] "Wed Jun 17 17:28:49 2015"
> Sys.Date()
[1] "2015-06-17"
> Sys.time()
[1] "2015-06-17 17:28:49 JST"
> 
> # lubridate()の関数で取得
> today()
[1] "2015-06-17"
> now()
[1] "2015-06-17 17:28:49 JST"
> here()
[1] "2015-06-17 17:28:49 JST"

now()は指定したtimezoneの現在時刻、here()はローカル環境の現在時刻をPOSIXctオブジェクトで返してくれる。
now()はtimezoneを指定しなくてもローカルtimezoneを返してくれるのでnow()でよさそう。


その他のlubridateパッケージの関数

他の関数の使い方をメモしとく。

関数 用途 備考
year() 年の取得・セット
month() 月の取得・セット label=TでJan, Feb, abbr=FでJanuary, February表記
(データ型は順序付き因子型になる)
day(), mday() 日の取得・セット
yday() 日の取得・セット 1年の何日目か
week() 週の取得・セット
wday() 曜日の取得・セット label=TでSun, Mon, abbr=FでSunday, Monday表記
(データ型は順序付き因子型になる)
hour() 時の取得・セット
minute() 分の取得・セット
second() 秒の取得・セット
round_date() 日付オブジェクトの四捨五入
ceiling_date() 日付オブジェクトの切り上げ
floor_date() 日付オブジェクトの切り捨て
leap_year() うるう年の判定


実行すると次のようになる。

> current_time <- ymd_hms("2015-07-16 12:34:56")
> current_time
[1] "2015-07-16 12:34:56 UTC"

> # 年
> year(current_time)
[1] 2015

> # 月
> month(current_time)
[1] 7
> month(current_time, label=T)
[1] Jul
12 Levels: Jan < Feb < Mar < Apr < May < Jun < Jul < Aug < Sep < ... < Dec
> month(current_time, label=T, abbr=F)
[1] July
12 Levels: January < February < March < April < May < June < ... < December

> # 日
> day(current_time)
[1] 16
> mday(current_time)
[1] 16
> yday(current_time)
[1] 197

> # 週
> week(current_time)
[1] 29

> # 曜日
> wday(current_time)
[1] 5
> wday(current_time, label=T)
[1] Thurs
Levels: Sun < Mon < Tues < Wed < Thurs < Fri < Sat
> wday(current_time, label=T, abbr=F)
[1] Thursday
7 Levels: Sunday < Monday < Tuesday < Wednesday < Thursday < ... < Saturday

> # 四捨五入、切り上げ、切り捨て
> round_date(current_time,"day")
[1] "2015-07-17 UTC"
> ceiling_date(current_time,"day")
[1] "2015-07-17 UTC"
> floor_date(current_time,"day")
[1] "2015-07-16 UTC"

> round_date(current_time,"month")
[1] "2015-08-01 UTC"
> ceiling_date(current_time,"month")
[1] "2015-08-01 UTC"
> floor_date(current_time,"month")
[1] "2015-07-01 UTC"

> round_date(current_time,"year")
[1] "2016-01-01 UTC"
> ceiling_date(current_time,"year")
[1] "2016-01-01 UTC"
> floor_date(current_time,"year")
[1] "2015-01-01 UTC"

> # うるう年の判定
> leap_year(current_time)
[1] FALSE
> leap_year(current_time + years(1))
[1] TRUE

自分は日付の加工をRで行なうことは少ないけれど読み込み時にformatを指定しなくても良いのは便利そう。
その他の参考もメモしとく。