2017-12-29 51 views
4

laws이라는 각 법에 대한 행이있는 df가 있습니다 (각 id마다 하나씩). laws에서 idyear DF 출력을 얻기 위해 어떻게 효율적으로 몇 가지 코드를 작성 가겠어요각 ID와 법칙 (시작 연도와 종료 연도가 포함 된 행)을 각 ID와 연도에 대한 행이있는 파일로 바꿉니다.

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 <- 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라고 df? 두 개의 법칙 변수는 idyear$year> = laws$beginyear이고 idyear$year이 < = laws$endyear 인 경우 표시기 변수 == 1입니다.

저는 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 항목이 0이 아닌 경우 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 이것은 우리 magrittr 파이프를 사용한하기 (1)을 표현하는 것과 같은 용액이다. 파이프 연산자의 혼합에 주목하십시오.

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

확인. 고정되어 있음. –

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 dataframe로 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 

라이브러리 :

dplyr (arrange, 정말 필요하지 않는)

데이터 : 해결책은 를 사용

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)