2011-02-25 3 views
2

fyear, ticdcvt (회계 연도, 시세 및 총 전환 가능 채무)의 세 개의 열이있는 긴 데이터 프레임이 있습니다. 약 18 회계 연도와 수천 개의 시세가 있습니다. 나는 dcvt이 1 년에서 다음 해로 올라갈 때 하나 인 표시기 변수를 추가하고 싶습니다.값이 1 년에서 다음 연도로 증가 할 때 표시기 변수를 긴 데이터 프레임에 추가합니다.

나는 fyear 열을 잃어 버렸고 다시 가져 오는 방법을 알 수 없었습니다. ddply을 사용해 보았습니다.

library(plyr) 
temp <- data.frame(fyear = rep(1992:2009, 10), tic = rep(letters[1:10], each = 18), dcvt = rnorm(180, 200, 10)) 
my.fun <- function(x) x <- c(0, ifelse(tail(x, -1) - head(x, -1) > 0, 1, 0)) 
temp2 <- ddply(temp, "tic", colwise(my.fun, "dcvt")) 

은 또한 다음 for 루프를 실행 reshape2 패키지와 함께 폭으로 캐스팅하려고했으나 물론, 그 영원히했다.

신속하게 처리 할 수있는 방법이 있습니까? 내가 zoo 객체를 넓히고 diff을 사용해야하나요? 나는 할 수 있으면 시계열을 지나는 것을 피하고 싶다. 감사!

답변

5

ddply 때로는 크게 도움에 tranform를 사용하여 :

ddply(temp, .(tic), transform, dcvt=c(0, diff(dcvt)>0)) 
+0

감사합니다. 신기한 실수; 나는 심지어 몇 달 전 여기서 'ddply'트릭을 '변형'시키는 것을 보았습니다! –

2

ddpy() 아주 잘이 크기 (10^2)의 데이터 세트를 처리합니다. 그러나, 더 큰 데이터 세트에 대한 당신은 반드시 전체 dataframe을 돌려 줄 필요가없는 상황에서, 나는 다음과 같은 do.call + lapply 해결책이라고 생각 :

my.fun <- function(cur.tic){ 
    as.numeric(diff(temp$dcvt[temp$tic == cur.tic]) > 0) 
} 

do.call("c", lapply(unique(temp$tic), my.fun)) 

는 성능 보수를 설명하기를 (부당 벡터 대 주어 데이터 프레임 문제), OP의 샘플 데이터를 가져 와서 10^4, 10^5 및 10^6 크기의 새 데이터 프레임을 만든 다음 system.time()을 @ kohske의 ddply 솔루션과 위의 솔루션에서 실행했습니다.

원본 데이터 (10^2) :

> system.time(do.call("c", lapply(unique(temp$tic), my.fun))) 
    user system elapsed 
    0.000 0.000 0.003 
> system.time(ddply(temp, .(tic), transform, dcvt=c(0, diff(dcvt)>0))) 
    user system elapsed 
    0.020 0.000 0.013 
,451,515,

10^4 샘플 데이터

> system.time(do.call("c", lapply(unique(temp.2$tic), my.fun))) 
    user system elapsed 
    0.000 0.000 0.002 
> system.time(ddply(temp.2, .(tic), transform, dcvt=c(0, diff(dcvt)>0))) 
    user system elapsed 
    0.040 0.000 0.036 

10^5 개 샘플 데이터

> system.time(do.call("c", lapply(unique(temp.3$tic), my.fun))) 
    user system elapsed 
    0.000 0.000 0.004 
> system.time(ddply(temp.3, .(tic), transform, dcvt=c(0, diff(dcvt)>0))) 
    user system elapsed 
    0.270 0.000 0.279 

10^6 샘플 데이터

> system.time(do.call("c", lapply(unique(temp.4$tic), my.fun))) 
    user system elapsed 
    0.010 0.000 0.018 
> system.time(ddply(temp.4, .(tic), transform, dcvt=c(0, diff(dcvt)>0))) 
    user system elapsed 
    6.110 0.070 6.186 

아니 불만 ddply()에 대한 -이 아니라, 단지 노력 최근에 많은 대상 데이터 세트를 사용하여 매우 비슷한 문제를 해결하면서 유용한 코드를 공유했습니다.

+1

실제로 ddply가 데이터 프레임을 반환하고 함수가 벡터를 반환하는 적절한 비교는 아닙니다. ave는 아마 심지어 더 빠를 것입니다 – hadley

+0

+1 그게 좋은 지적입니다, @ 해들리. 나는 내가 최근에 작업하고 있던 상당히 큰 데이터 세트 (10^7)로 매우 효율적이라는 것을 알게 된 접근 방식의 정교함만큼 'ddply'에 대한 내 의견을 말하지는 않았다. 이 점을 명확히하기 위해 내 대답을 편집하십시오! – ashaw