2013-10-29 5 views
1

아래 코드에서 plyr 또는 data.table을 사용하여 med.val2를 우아하게 계산하는 방법에 대한 통찰력이 있는지 궁금합니다.그룹 별 중형자 R

library(plyr) 

설치 예 데이터

루프에 의해
data <- data.frame(id1 = 1:20, id2 = rep(letters[1:4], 5), vals=rnorm(20)) 

먼저 계산 그룹 중앙값

data$med.val <- rep(0, 20) 
for (ind in 1:20) data$med.val[ind] <- median(data$vals[data$id2==data$id2[ind]]) 

지금 plyr

를 사용
data <- ddply(data, .(id2), mutate, med.val.plyr=median(vals)) 

는 같아야

R에서 초점 행

# Median of values corresponding to 
# data$id1!=data$id1[ind] & data$id2==data$id2[ind] 
data$med.val2 <- rep(0, 20) 
for (ind in 1:20) data$med.val2[ind] <- median(data$vals[data$id1!=data$id1[ind] & data$id2==data$id2[ind]]) 

제외한 동일한 ID2와 행

all.equal(data$med.val, data$med.val.plyr) 

메디안은, I는 전형적으로 효율적기로 값을 계산하거나 plyr data.table를 사용한다. 내 실제 데이터와 함수는 더 복잡하지만 구조가 동일합니다. 초점 행을 제외하고 공통 식별자가있는 행의 데이터를 사용하여 함수를 계산해야합니다. 그리고 나는 그것을 효율적이고 우아하게하는 방법을 이해할 수 없습니다.

답변

1

나는 보조적인 기능을 위해 가서 median에서와 같은 방법을 사용할 것이다.

med2 <- function(x) sapply(seq_along(x), function(ind) median(x[-ind])) 
data <- ddply(data, .(id2), mutate, med.val2.plyr=med2(vals)) 
all.equal(data$med.val2, data$med.val2.plyr) 

또는 같은 일의 data.table 방법 :

dt <- data.table(data, key="id2") 
med2 <- function(x) sapply(seq_along(x), function(ind) median(x[-ind])) 
dt[, med.val2.dt:=med2(vals), by=id2] 
all.equal(dt$med.val2, dt$med.val2.dt) 
1

데이터 테이블에 한 가지 가능한 솔루션 : @shadow에 의해 사람과 함께이 솔루션 :

dt = data.table(data) 
dt[,med.val3 := sapply(.SD$id1, function(x) median(.SD[id1!=x,vals])), by=id2] 

편집에 비교적 간결하고 우아합니다. 그들은 또한 이런 종류의 해결책으로 당신이 바라는만큼 효율적으로 갈 것입니다. 그러나 더 효율적인 구현을 코딩 할 수 없다면 leave-one-out 통계를 계산하는 것은 O (n^2) 연산이 될 것입니다. 평균과 중앙값 같은 것들, 이것은 예를 들어, 매우 간단합니다 :

looMedian<-function(x){ 
    rng<-range(x) 
    bigMedian<-median(c(x,rng[2]+1)) 
    smallMedian<-median(c(x,rng[1]-1)) 
    med<-median(x) 
    ret<-ifelse(x<med,bigMedian,smallMedian) 
    wm<-which(x==med) 
    if(length(wm)==0) 
    return(ret) 
    ret[wm]<-median(x[-wm[1]]) 
    ret 
} 

이 훨씬 더 효율적으로 순진 솔루션보다이 같은이 사건이 달라집니다 가능 여부

looMedianSlow<-function(x){ 
    sapply(seq_along(x),function(z) median(x[-z])) 
} 


> xx<-rnorm(100) 
> all.equal(looMedianSlow(xx),looMedian(xx)) 
[1] TRUE 
> xx<-rnorm(101) 
> all.equal(looMedianSlow(xx),looMedian(xx)) 
[1] TRUE 
> microbenchmark(looMedianSlow(xx),looMedian(xx)) 
Unit: microseconds 
       expr  min  lq median  uq  max neval 
looMedianSlow(xx) 5174.193 5264.951 5308.5075 5398.6950 44771.062 100 
    looMedian(xx) 241.462 248.513 260.0685 278.3615 3495.796 100 

당신이 계산하려고하는 통계.