2013-02-08 3 views
1

id 변수에 대한 중복 값이 ​​포함 된 데이터 프레임 (~ 5000 행, 6 열)이 있습니다. 또 다른 연속 변수 x을 가지고 있는데, 각 값은 각 복제본에 대해 합계를 내고 싶습니다. id. 관찰 시간은 시간에 따라 다르며 변수는 yearmonth입니다. 각 복제본의 시간순으로 첫 번째 관찰을 유지하고 id 후속 반복문을이 첫 번째 관찰에 추가하고 싶습니다.중복을 합친 다음 첫 번째 발생을 제외한 모든 것을 제거합니다.

나는 가지고있는 것과 유사한 더미 데이터를 포함했습니다 : dat1. 또한 원하는 결과의 구조를 보여주는 데이터 세트를 포함 시켰습니다 : outcome.

저는 두 가지 전략을 시도했지만, 어느 것도 나에게 원하는 것을주지는 못합니다 (아래 참조). 첫 번째 전략은 나에게 x에 대한 올바른 값을 제공하지만 내 연월 열이 느슨합니다. 모든 첫 번째 중복 값 id 값을 유지해야합니다. 두 번째 전략은 x 값을 올바르게 합산하지 않습니다.

원하는 결과를 얻는 방법에 대한 제안 사항에 많은 감사를드립니다.

# dummy data set 
set.seed(179) 
dat1 <- data.frame(id = c(1234, 1321, 4321, 7423, 4321, 8503, 2961, 1234, 8564, 1234), 
        year = rep(c("2006", "2007"), each = 5), 
        month = rep(c("December", "January"), each = 5), 
        x = round(rnorm(10, 10, 3), 2)) 

# desired outcome 
outcome <- data.frame(id = c(1234, 1321, 4321, 7423, 8503, 2961, 8564), 
         year = c(rep("2006", 4), rep("2007", 3)), 
         month = c(rep("December", 4), rep("January", 3)), 
         x = c(36.42, 11.55, 17.31, 5.97, 12.48, 10.22, 11.41)) 

# strategy 1: 
library(plyr) 
dat2 <- ddply(dat1, .(id), summarise, x = sum(x)) 

# strategy 2: 
# partition into two data frames - one with unique cases, one with dupes 
dat1_unique <- dat1[!duplicated(dat1$id), ] 
dat1_dupes <- dat1[duplicated(dat1$id), ] 

# merge these data frames while summing the x variable for duplicated ids 
# with plyr 
dat3 <- ddply(merge(dat1_unique, dat1_dupes, all.x = TRUE), 
       .(id), summarise, x = sum(x)) 
# in base R 
dat4 <- aggregate(x ~ id, data = merge(dat1_unique, dat1_dupes, 
        all.x = TRUE), FUN = sum) 

답변

5

나는 다른 금액을 가지고,하지만 있었다 나는 씨앗을 잊어 C/B :

> dat1$x <- ave(dat1$x, dat1$id, FUN=sum) 
> dat1[!duplicated(dat1$id), ] 
    id year month  x 
1 1234 2006 December 25.18 
2 1321 2006 December 15.06 
3 4321 2006 December 15.50 
4 7423 2006 December 7.16 
6 8503 2007 January 13.23 
7 2961 2007 January 7.38 
9 8564 2007 January 7.21 

(그것을 더 안전합니다 사본을 작성하는 것이 더 좋으며 주문 단계를 추가해야 할 수도 있습니다.)

+0

와우, 훌륭합니다! 저는 수학을 퍼지하지 않았습니다 - 저는 코드 상단에 시드 번호를 복사하지 않았을 것이라고 생각합니다. 나는 그 시드를 사용할 때 코드를 사용하여 '결과'데이터 세트에 내린 값을 얻습니다. 그런 깔끔한 두 개의 라이너를 가져 주셔서 감사합니다! – Chris

+0

Ooops. 죄송합니다. 작은 데이터 였기 때문에 무작위로 설정된 시드를 놓친 것 같습니다. 프레임. –

3

당신은 data.table (plyr보다 더 빠르고 효율적으로, 더 많은 메모리) 자기 결합 약간의 재미는 '첫 번째'mult =을 사용하여

이 작업을 수행 할 수있다. id 년 및 월별 키잉은 id, year, month 순으로 정렬됩니다.

library(data.table) 
DT <- data.table(dat1, key = c('id','year','month')) 


# setnames is required as there are two x columns that get renamed x, x.1 
DT1 <- setnames(DT[DT[,list(x=sum(x)),by=id],mult='first'][,x:=NULL],'x.1','x') 

또는 간단한 방법 :

DT = as.data.table(dat1) 

DT[,x:=sum(x),by=id][!duplicated(id)] 

    id year month  x 
1: 1234 2006 December 36.42 
2: 1321 2006 December 11.55 
3: 4321 2006 December 17.31 
4: 7423 2006 December 5.97 
5: 8503 2007 January 12.48 
6: 2961 2007 January 10.22 
7: 8564 2007 January 11.41 
+1

귀하의 솔루션에 너무 고마워요! 위의'data.table' 솔루션은 완벽하게 작동하지만 구문은 (data.table에 익숙하지 않은) 저에게 끔찍한 것처럼 보입니다. 편집하기 전에 원래 답변에'plyr' 해결책이 있다는 것을 알았습니다. 당신의'plyr' 코드는'Error : length (rows) == 1은 TRUE가 아닙니다 .'라는 에러를주었습니다. 시간이 있다면 작동하는'plyr' 예제를 제공 하시겠습니까? 구문이 나에게 더 이해하기 쉽고 'data.table'성능 향상이 5k 행의 데이터에 중요하지 않음을 알았습니다. (앞으로는이를 확장 할 필요가 없습니다.) – Chris

+0

@Chris, 내'plyr' 해결책이 올바르지 않습니다 (그래서 내가 그것을 삭제했기 때문입니다). 데이터가 연도별로 정렬되도록 (올바르게) 보장 할 수 있다면. ddply (dat1,. (id), summary, x = sum (x), month = month [1], year = year [1])'이 작동합니다. – mnel

관련 문제