我有一个问题,就是找到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
计算平均值。
必须有一种更有效的方法来做到这一点。有没有人有任何见解?欢呼声。
答案 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))