找出R中每个因子的2个最大值

时间:2014-08-08 23:38:44

标签: r dataset max subset

我有一个问题,就是找到C列的两个最大值,A列中的每个唯一ID,然后计算B列的平均值。我的数据样本在这里:

ID  layer   weight
1   0.6843629   0.35
1   0.6360772   0.70
1   0.6392318   0.14
2   0.3848640   0.05
2   0.3882660   0.30
2   0.3877026   0.10
2   0.3964194   0.60
2   0.4273218   0.02
2   0.3869507   0.12
3   0.4748541   0.07
3   0.5853659   0.42
3   0.5383678   0.10
3   0.6060287   0.60
4   0.4859274   0.08
4   0.4720740   0.48
4   0.5126481   0.08
4   0.5280899   0.48
5   0.7492097   0.07
5   0.7220433   0.35
5   0.8750000   0.10
5   0.8302752   0.50
6   0.4306283   0.10
6   0.4890895   0.25
6   0.3790714   0.20
6   0.5139686   0.50
6   0.3885678   0.02
6   0.4706815   0.05

对于每个ID,我想计算图层的平均值,仅使用具有两个最高权重的行。

我可以使用R中的以下代码执行此操作:

ind.max1 <- ddply(index1, "ID", function(x) x[which.max(x$weight),]) 
    dt1 <- data.table(index1, key=c("layer"))
    dt2 <- data.table(ind.max1, key=c("layer"))
    index2 <- dt1[!dt2]
    ind.max2 <- ddply(index2, "ID", function(x) x[which.max(x$weight),])
ind.max.all <- merge(ind.max1, ind.max2, all=TRUE)
ind.ndvi.mean <- as.data.frame(tapply(ind.max.all$layer, list(ind.max.all$ID), mean))

这使用ddply选择每个ID的第一个最高权重值,并将其放入带有图层的数据框中。然后使用data.table从原始数据框中删除这些最高权重值。然后,我重复ddply选择最大值,并将两个最大权重值数据帧合并为一个。最后,用tapply计算平均值。 必须有一种更有效的方法来做到这一点。有没有人有任何见解?欢呼声。

3 个答案:

答案 0 :(得分:3)

您可以使用data.table

 library(data.table)
 setDT(dat)[, mean(layer[order(-weight)[1:2]]), by=ID]
 #   ID Meanlayer
 #1:  1 0.6602200
 #2:  2 0.3923427
 #3:  3 0.5956973
 #4:  4 0.5000819
 #5:  5 0.7761593
 #6:  6 0.5015291
  • 以降序weight
  • 订购order(-weight)
  • 从按组[1:2]
  • 创建的订单ID中选择前两个
  • 根据索引layer
  • 对相应的layer[order..]行进行子集化
  • 执行mean

或者,在1.9.3(当前开发版本)或下一版本中,导出函数setorder以按任意顺序重新排序data.tables,按引用

require(data.table) ## 1.9.3+
setorder(setDT(dat), ID, -weight) ## dat is now reordered as we require
dat[, mean(layer[1:min(.N, 2L)]), by=ID]

首先订购,我们会避免为每个组调用order()ID中的唯一值)。对于更多群体来说,这将更有利。 setorder()效率高于order(),因为它不需要创建数据副本。

答案 1 :(得分:1)

这实际上是StackOverflow的问题......无论如何! 不知道下面的版本是否足够有效...

s.ind<-tapply(df$weight,df$ID,function(x) order(x,decreasing=T))
val<-tapply(df$layer,df$ID,function(x) x)

foo<-function(x,y) list(x[y][1:2])
lapply(mapply(foo,val,s.ind),mean)

答案 2 :(得分:0)

我认为这样做会。假设数据被称为dat

> sapply(split(dat, dat$ID), function(x) { 
      with(x, {
          mean(layer[ weight %in% rev(sort(weight))[1:2] ])
          })
      })
#         1         2         3         4         5         6 
# 0.6602200 0.3923427 0.5956973 0.5000819 0.7761593 0.5015291 

您可能希望将na.rm = TRUE作为mean的第二个参数包含在内,以便考虑包含NA值的所有行。

或者,mapply可能更快,并且只是以不同的顺序具有完全相同的代码,

mapply(function(x) { 
      with(x, {
          mean(layer[ weight %in% rev(sort(weight))[1:2] ])
          })
      }, split(dat, dat$ID))