2012-03-21 3 views
1

50000 개의 행과 200 개의 행을 가진 데이터 프레임이 있습니다. 데이터에 중복 행이 있고 R에서 집계 함수를 사용하여 중복 중 최대 변동 계수를 갖는 행을 선택하여 데이터를 집계하려고합니다. 집계에서는 기본적으로 "평균", "합계"를 사용할 수 있지만 계수는 사용할 수 없습니다. 변화. 예 : 집계 (데이터, as.columnname, FUN = 평균) 잘 작동합니다.집계의 변동 계수 사용하기

변동 계수를 계산할 수 있지만 집계와 함께 사용하는 방법을 알 수없는 맞춤 함수가 있습니다.

co.var < - 함수 (X) ( 100 * SD (X)/평균 (X)를 )

제가 시도 집합 (데이터 as.columnname 함수 (X) 최대 (co.var (x, data [index (x),]))) 개체 x가 없으므로 오류가 발생합니다.

의견이 있습니다.

+1

를? – csgillespie

답변

4

귀하의 문제를 이해한다고 가정하면 aggregate() 대신 tapply()을 사용하는 것이 좋습니다 (자세한 내용은 ?tapply 참조). 그러나, 최소한의 작업 예제는 매우 도움이 될 것입니다.

co.var <- function(x) (100*sd(x)/mean(x)) 

## Data with multiple repeated measurements. 
## There are three things (ID 1, 2, 3) that 
## are measured two times, twice each (val1 and val2) 
myDF<-data.frame(ID=c(1,2,3,1,2,3),val1=c(20,10,5,25,7,2), 
    val2=c(19,9,4,24,4,1)) 

## Calculate coefficient of variation for each measurement set 
myDF$coVar<-apply(myDF[,c("val1","val2")],1,co.var) 

## Use tapply() instead of aggregate 
mySel<-tapply(seq_len(nrow(myDF)),myDF$ID,function(x){ 
    curSub<-myDF[x,] 
    return(x[which(curSub$coVar==max(curSub$coVar))]) 
}) 

## The mySel vector is then the vector of rows that correspond to the 
## maximum coefficient of variation for each ID 
myDF[mySel,] 

편집 :

중 하나는 다음과 같습니다 빠른 방법이 있습니다. 그러나 40000x100 데이터 세트의 경우 위의 코드는 내 컴퓨터에서 16-20 초 밖에 걸리지 않았습니다.

# Create a big dataset 

myDF <- data.frame(val1 = c(20, 10, 5, 25, 7, 2), 
    val2 = c(19, 9, 4, 24, 4, 1)) 
myDF <- myDF[sample(seq_len(nrow(myDF)), 40000, replace = TRUE), ] 
myDF <- cbind(myDF, rep(myDF, 49)) 
myDF$ID <- sample.int(nrow(myDF)/5, nrow(myDF), replace = TRUE) 

# Define a new function to work (slightly) better with large datasets 

co.var.df <- function(x) (100*apply(x,1,sd)/rowMeans(x)) 

# Create two datasets to benchmark the two methods 
# (A second method proved slower than the third, hence the naming) 

myDF.firstMethod <- myDF 
myDF.thirdMethod <- myDF 

시간 원본 방법

startTime <- Sys.time() 
myDF.firstMethod$coVar <- apply(myDF.firstMethod[, 
    grep("val", names(myDF.firstMethod))], 1, co.var) 
mySel <- tapply(seq_len(nrow(myDF.firstMethod)), 
    myDF.firstMethod$ID, function(x) { 
    curSub <- myDF.firstMethod[x, ] 
    return(x[which(curSub$coVar == max(curSub$coVar))]) 
}, simplify = FALSE) 
endTime <- Sys.time() 

R> endTime-startTime 
Time difference of 17.87806 secs 

시간 두 번째 방법

startTime3 <- Sys.time() 
coVar3<-co.var.df(myDF.thirdMethod[, 
    grep("val",names(myDF.thirdMethod))]) 
mySel3 <- tapply(seq_along(coVar3), 
    myDF[, "ID"], function(x) { 
    return(x[which(coVar3[x] == max(coVar3[x]))]) 
}, simplify = FALSE) 
endTime3 <- Sys.time() 

R> endTime3-startTime3 
Time difference of 2.024207 secs 

그리고 우리가 같은 결과를 얻을 수 있는지 확인 :

R> all.equal(mySel,mySel3) 
[1] TRUE 

추가가를 원래 게시물에서 변경,에서 편집 된 코드는 주어진 ID에 대해 가장 높은 CV를 가진 행이 여러 개있을 수 있다고 간주합니다. 따라서, 편집 된 코드의 결과, 당신은 mySel 또는 mySel3 객체를 unlist해야한다 얻을 :`as.columnname`은 무엇입니까

myDF.firstMethod[unlist(mySel),] 

myDF.thirdMethod[unlist(mySel3),] 
+2

그게 잘 작동합니다. 이것으로 우리는 최소 coef로 행을 얻는다. var, "min (curSub $ coVar)"을 "max (curSub $ coVar)"로 변경하면 최대로 처리 할 수 ​​있습니다. 도와 주셔서 감사합니다. – piyush

+0

예, 죄송합니다. 응답을 편집하여 최대 값을 반환합니다. 죄송합니다. – BenBarnes

+0

더 빠른 방법이 있습니까? 약 100 개의 열과 40000 개의 행이있는 더 큰 데이터 프레임에 오랜 시간이 걸립니다. – piyush