2012-03-21 8 views
1

私は50000行と200列のデータフレームを持っています。データに重複する行があり、Rの集約関数を使用して重複係数の最大変動係数を持つ行を選択してデータを集計したいとします。集計では、デフォルトでは "平均"を使用できますが、coefでは使用できません。変化。 たとえば、 集計(データ、as.columnname、FUN =平均) 正常に動作します。集計における変動係数の使用R

私は変動係数を計算するカスタム関数を持っていますが、それを集計でどのように使用するかはわかりません。

co.var < - 機能(X) ( 100 *のSD(X)/平均値(X) )

Iは 集約(データ、as.columnname、関数(x)の最大値を試みました(co.var(x、data [index(x)、]))) オブジェクトxが見つからないため、エラーが発生しています。

何か提案があります。

+1

'as.columnname'は何ですか? – 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,] 

EDIT:

は、は、以下のいずれかで、速い方法があります。しかし、40000 x 100のデータセットでは、上記のコードは私のマシンで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を持つ行が複数あると考えています。そのため、編集したコードから結果を取得するには、mySelmySel3オブジェクトをunlistする必要があります。

myDF.firstMethod[unlist(mySel),] 

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

それはうまく動作します。これで、最小の係数を持つ行が得られます。 var、 "min(curSub $ coVar)"を "max(curSub $ coVar)"に変更するだけで最大限の処理ができます。助けてくれてありがとう。 – piyush

+0

はい、申し訳ありません。最大値を返すように答えを編集しました。ごめんなさい。 – BenBarnes

+0

これを行うにはより速い方法がありますか?それは、約100列と40000行のより大きなデータフレームのために長い時間がかかります。 – piyush

関連する問題