私はグループと日付がdata.frame
です。各グループの最小期間の日付範囲内に欠けている日付をすべて記入するにはどうすればよいですか?グループで不足している日付を記入する方法
dplyr
でこれを行うのが理想です。しかし、最終的には、可能な限り数行の(読みやすい)コードでこれを効率的に実行したいと思っています。以下は最小限の例です。私は実際に多くの日付とグループを持っています。私のアプローチはどちらも一見醜いものに見える。より良い方法がなければなりません、そうですか?
#### setup ####
library(sqldf)
library(dplyr)
df <- data.frame(the_group = rep(LETTERS[1:2], each=3), date = Sys.Date() + c(0:2, 1:3), stringsAsFactors = F) %>%
tbl_df() %>%
slice(-2) # represents that I may be missing data in a range!
#### dplyr approach with cross join dummy ####
full_seq <- data.frame(cross_join_dummy = 1, date = seq.Date(from=min(df$date), to=max(df$date), by = "day"))
range_by_group <- df %>%
group_by(the_group) %>%
summarise(min_date = min(date), max_date = max(date)) %>%
ungroup() %>%
mutate(cross_join_dummy = 1)
desired <- range_by_group %>%
inner_join(full_seq, by="cross_join_dummy") %>%
filter(date >= min_date, date <= max_date) %>%
select(the_group, date)
#### sqldf approach ####
full_seq <- data.frame(date = as.character(seq.Date(from=min(df$date), to=max(df$date), by="day")))
df <- df %>%
mutate(date = as.character(date))
range_by_group <- sqldf("
SELECT the_group, MIN(date) AS min_date, MAX(date) AS max_date
FROM df
GROUP BY the_group
")
desired <- sqldf("
SELECT rbg.the_group, fs.date
FROM range_by_group rbg
JOIN full_seq fs
ON fs.date BETWEEN rbg.min_date AND rbg.max_date
")
「パッケージなし」アプローチがなぜ機能するのかを理解することがなおも問題です。特に 'the_group [1]'と 'with' – lowndrul
と同じです。do.call(" rbind "と同じです.df、df $ the_group、function(x) data.frame(the_group = x $ the_group [ 1]、date = seq(min(x $ date)、max(x $ date)、by = "day"))) '短縮化のために' with'を使いました。 'the_group'はグループ内では定数なので、データフレームに2つの異なる長さベクトルを混在させることができないので、最初のコンポーネントを使用しました。 –
今日の改良点を踏まえて少し拡張された答え(OCT 2017 )は分割の代わりに 'nest()'機能を使い、OPがここで 'tidyverse'の例として使用するマップの組み合わせになります。やや清潔なプレゼンテーション。さもなければ、ここの論理は同じままです。 – jacobsg