我有一个50000行和200列的数据框。数据中有重复的行,我想通过使用R中的聚合函数选择具有最大变异系数的行来聚合数据。使用聚合我可以使用“mean”,默认使用“sum”但不使用coef。变异。 例如 aggregate(data,as.columnname,FUN = mean) 工作正常。
我有一个用于计算变异系数的自定义函数,但不确定如何将它与聚合一起使用。
co.var< - function(x) ( 100 * SD(X)/平均值(x)的 )
我试过了 aggregate(data,as.columnname,function(x)max(co.var(x,data [index(x),]))) 但由于找不到对象x,它会发出错误。
任何建议!
答案 0 :(得分:4)
假设我理解您的问题,我建议您使用tapply()
代替aggregate()
(有关详细信息,请参阅?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,]
修改强>
有更快的方法,其中一种方法如下。但是,对于40000乘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。因此,要从已编辑的代码中获取结果,您必须unlist
mySel
或mySel3
个对象:
myDF.firstMethod[unlist(mySel),]
myDF.thirdMethod[unlist(mySel3),]