DBに何日分かデータが入っていなかったため、DBの中身をチェックする必要がありました。 そこで、以下の日付の範囲を取る関数を作り、DBの戻り値にないものを探すようにしました。
library(dplyr) library(purrr) # 日付の範囲を取る関数 date_range <- function(begin_date, end_date) { return( seq( as.Date(begin_date, format='%Y%m%d'), as.Date(end_date, format='%Y%m%d'), by='days' ) ) } # チェックした日付の範囲 date_range('20160101', '20160109') # [1] "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" "2016-01-05" "2016-01-06" "2016-01-07" "2016-01-08" # [9] "2016-01-09" # DBの戻り値をチェック date_range('20160101', '20160109') %>% purrr::keep(~ !. %in% db_data$date) # db_dataはdateカラムに日付が入ってるデータフレームだと考えてください # [1] "2016-01-07" # 7日のデータが入ってなかった!
ただし、as.Date(***, format='%Y%m%d')
と2回も書いてしまっており、イケてる書き方ではありません。
そこで、日付の文字列のリストを、purrr::map
関数を使ってDate型のリストに変換し、
(Pythonの引数展開のように)リストを展開して引数として与える方法は無いかと考えました。
# pythonでRの関数を使った擬似コード from functools import partial # 日付の文字列のリストをDate型のリスト(正確にはジェネレーターだけど)に変換する date_scope_str = ['20160101', '20160109'] date_scope_dt = map(partial(as.Date, format='%Y%m%d'), date_scope_str) # 引数に*を付けることで、リストを展開して与える seq_days = partial(seq, by='days') seq_days(*date_scope_dt)
Rでも引数を展開し、更にパイプ(%>%
)で与えられると便利そうです。
というわけで、「R 引数展開」や「R argument expansion」とかで検索すると、Rでは引数の展開にdo.call
関数を使うように書いてました。
これを使ってdate_range
関数を再実装するとこんな感じになりました。
date_range(begin_date, end_date) { return( list(begin_date, begin_date) %>% purrr::map(as.Date, format='%Y%m%d') %>% do.call(what = function(x, y){seq(x, y, by = 'days')}) ) }
日付の文字列のリストをpurrr
のmap
関数でDate型のリストに変換し、それをdo.call
でseq
関数に渡しています。
as.Date(***, format='%Y%m%d')
を1箇所にまとめることができました。
ただし、引数の順番やby = 'days'
の引数の部分適用のため、what =
の後にラムダ式を繋げてキモい感じになっています。
そこで、以下のような部分適用の関数を作ってみました。
# 引数展開&部分適用の関数 # purrrとかdplyrにこういう関数無いかな… expantion <- function(args, func, ...) { return( do.call( function(x, y) { func(x, y, ...) }, args ) ) } date_range <- function(begin_date, end_date) { return ( list(begin_date, end_date) %>% purrr::map(as.Date, format='%Y%m%d') %>% expantion(seq, by='days') # スッキリ! ) } date_range('20160101', '20160109') # [1] "2016-01-01" "2016-01-02" "2016-01-03" "2016-01-04" "2016-01-05" "2016-01-06" "2016-01-07" "2016-01-08" # [9] "2016-01-09"
ただ、これを毎回実装するのもアレだし、↑の関数だと引数が2つの場合しか対応できないし、
他人に渡すとき困るし、微妙な感じです。
purrr
のlift
系の関数がdo.call
のラッパーらしいのでこんなことができるんじゃないかと思ってるんですが、
いまいち使い方が分かりません。