2017-12-29 68 views
4

lawsという名前のdfがあります。私は2番目作成したいから各IDと法律の行(開始年と終了年)を各IDと年の行を含むファイルに変換します

laws <- data.frame(id=c(1,2,3),beginyear=c(2001,2002,2005),endyear=c(2003,2005,2006), law1=c(0,0,1), law2=c(1,0,1)) 

は、各idと年間の行でidyearと呼ば:

idyear <- data.frame(id=c(rep(1,6),rep(2,6),rep(3,6)), year=(rep(c(2001:2006),3)), law1=c(rep(0,16),1,1), law2=c(1,1,1,rep(0,13),1,1)) 

にはどうすれば効率的にlawsからidyear DFの出力を得るために、いくつかのコードを書くに行きますかdf? 2つの法則変数は、idyear$year> = laws$beginyearの場合は指標変数== 1、idyear$yearの場合は< = laws$endyearです。

私はRの初心者ですが、これを動作させるために何か試してみます(適用、ループなど)。

答えて

3

を使用したソリューション。最後のas.data.frame()はオプションで、tblをデータフレームに変換するだけです。

library(tidyverse) 

idyear <- laws %>% 
    mutate(year = map2(beginyear, endyear, `:`)) %>% 
    unnest() %>% 
    complete(id, year = full_seq(year, period = 1L), fill = list(law1 = 0L, law2 = 0L)) %>% 
    select(-beginyear, -endyear) %>% 
    as.data.frame() 
idyear 
# id year law1 law2 
# 1 1 2001 0 1 
# 2 1 2002 0 1 
# 3 1 2003 0 1 
# 4 1 2004 0 0 
# 5 1 2005 0 0 
# 6 1 2006 0 0 
# 7 2 2001 0 0 
# 8 2 2002 0 0 
# 9 2 2003 0 0 
# 10 2 2004 0 0 
# 11 2 2005 0 0 
# 12 2 2006 0 0 
# 13 3 2001 0 0 
# 14 3 2002 0 0 
# 15 3 2003 0 0 
# 16 3 2004 0 0 
# 17 3 2005 1 1 
# 18 3 2006 1 1 
+1

非常に滑らかです!私に 'map2'を見せてくれてありがとう - 私は' mutate'ですべての連続した年を作る方法を整理できませんでした。 –

4

1)基地expand.grid全てidyear組み合わせの18×2のデータフレームを作成し、次いでmergelawsと一緒に戻ってそれをマージします。任意のlaw1law2のエントリのうち、yearbeginyearendyearの間にないものをゼロにします。最後にbeginyearendyearの列を削除します。パッケージは使用されません。

g <- with(laws, expand.grid(year = min(beginyear):max(endyear), id = id)) 
m <- merge(g, laws) 
m[m$year < m$beginyear | m$year > m$endyear, c("law1", "law2")] <- 0 
m <- subset(m, select = - c(beginyear, endyear)) 

# check 
identical(m, idyear) 
## [1] TRUE 

2)magrittrこれは、(1)我々はそれを発現するようにmagrittrパイプラインを使用した以外は同様の溶液です。パイプ演算子の混合に注意してください。

library(magrittr) 

laws %$% 
    expand.grid(year = min(beginyear):max(endyear), id = id) %>% 
    merge(laws) %$% 
    { .[year < beginyear | year > endyear, c("law1", "law2")] <- 0; .} %>% 
    subset(select = - c(beginyear, endyear)) 

更新:を修正しました。 (2)を追加しました。

+0

私はそれも併合かもしれないと思ったが、その結果は要求されたものではない。マージ関数は範囲の間には入りません。 sqldfの魔法の一部が成功する可能性があります。 –

+0

はい、しかしOPはまた、彼が求めているものの建設を提供し、あなたの答えはそうではありません。 –

+0

OK。修正済みです。 –

3

mapplyの機能を使用すると便利です。

# Function to expand year between begin and end 
gen_data <- function(x_id, x_beginyear, x_endyear, x_law1, x_law2){ 
    df <- data.frame(x_id, x_beginyear:x_endyear, x_law1, x_law2) 
    df 
} 

idyearlst <- data.frame() 

idyearlst <- rbind(idyearlst, mapply(gen_data, laws$id, laws$beginyear, 
laws$endyear, laws$law1, laws$law2)) 

# Finally convert list to data.frame 
idyear <- setNames(do.call(rbind.data.frame, idyearlst), c("id", "year", "law1", "law2")) 

Result will be like: 
> idyear 
    id year law1 law2 
V1.1 1 2001 0 1 
V1.2 1 2002 0 1 
V1.3 1 2003 0 1 
V2.4 2 2002 0 0 
V2.5 2 2003 0 0 
V2.6 2 2004 0 0 
V2.7 2 2005 0 0 
V3.8 3 2005 1 1 
V3.9 3 2006 1 1 
+1

これまでのところ最高の答えです。おおよその刺し傷ではなく、実際に質問に答えます。 –

2

醜いアプローチの種類が、私はそれがベース、そしてあなたのlawsデータフレームとしてG.グロタンディークのgexpand.gridデータフレームを使用して、あなたは後にしているものを取得しますだと思います。

new.df <- data.frame(t(apply(g, 1, function(x){ 
    yearspan = laws[laws$id == x['id'], 'beginyear']:laws[laws$id == x['id'], 'endyear'] 
    law1 = laws$law1[laws$id == x['id'] & x['year'] %in% yearspan] 
    law2 = laws$law2[laws$id == x['id'] & x['year'] %in% yearspan] 
    x['law1'] = ifelse(length(law1 > 0), law1, 0) 
    x['law2'] = ifelse(length(law2 > 0), law2, 0) 
    return(x) 
}))) 

> new.df 
    id year law1 law2 
1 1 2001 0 1 
2 1 2002 0 1 
3 1 2003 0 1 
4 1 2004 0 0 
5 1 2005 0 0 
6 1 2006 0 0 
7 2 2001 0 0 
8 2 2002 0 0 
9 2 2003 0 0 
10 2 2004 0 0 
11 2 2005 0 0 
12 2 2006 0 0 
13 3 2001 0 0 
14 3 2002 0 0 
15 3 2003 0 0 
16 3 2004 0 0 
17 3 2005 1 1 
18 3 2006 1 1 

図書館:

dplyrarrange、本当に必要なため)

データ:

laws <- data.frame(id=c(1,2,3), 
        beginyear=c(2001,2002,2005), 
        endyear=c(2003,2005,2006), 
        law1=c(0,0,1), law2=c(1,0,1)) 

g <- with(laws, expand.grid(id = id, year = min(beginyear):max(endyear))) 
g <- arrange(g, id)