R中Pareto锋的快速计算

R中Pareto锋的快速计算,r,performance,if-statement,R,Performance,If Statement,因此,我试图计算R中的帕累托前沿(),我能够做到,但是,我不能有效地做到。特别是当点对的数量增加时,计算速度大大降低 所以一般来说,我要做的是检查所有非支配(或支配)对。现在我这样做的方法是找到所有这样的点对,比如xi>X 和yi>Y其中(xi,yi)是一对,并且X和Y代表所有点X和Y。现在,这一部分工作非常快速且易于实现,但是,还有一种可能性,即多个x值可能相同,但它们将具有不同的y值,因此在这种情况下,我希望能够识别具有最低y值的x值(对于具有相同y值但不同x值的点,反之亦然) 为了说明这一

因此,我试图计算
R
中的帕累托前沿(),我能够做到,但是,我不能有效地做到。特别是当点对的数量增加时,计算速度大大降低

所以一般来说,我要做的是检查所有非支配(或支配)对。现在我这样做的方法是找到所有这样的点对,比如xi>Xyi>Y其中(xi,yi)是一对,并且XY代表所有点XY。现在,这一部分工作非常快速且易于实现,但是,还有一种可能性,即多个x值可能相同,但它们将具有不同的y值,因此在这种情况下,我希望能够识别具有最低y值的x值(对于具有相同y值但不同x值的点,反之亦然)

为了说明这一点,这里有一幅来自维基百科的图片:

所以基本上我希望能够识别红线上的所有点

下面是我的代码,它确实有效,但对于大型数据集来说效率非常低:

#Example Data that actually runs quickly
x = runif(10000)
y = runif(10000)

pareto = 1:length(x)

for(i in 1:length(x)){
    cond1 = y[i]!=min(y[which(x==x[i])])
    cond2 = x[i]!=min(x[which(y==y[i])])
    for(n in 1:length(x)){
        if((x[i]>x[n]  &  y[i]>y[n]) | (x[i]==x[n] & cond1) | (y[i]==y[n] & cond2)){
            pareto[i] = NA
            break
        }
    }
}
#All points not on the red line should be marks as NA in the pareto variable
速度的减慢肯定来自于计算
(x[i]==x[n]&cond1)|(y[i]==y[n]&cond2)
,但我找不到解决方法或更好的布尔表达式来捕获我想要的所有内容。任何建议都非常感谢!

编辑:新版本:

system.time( {
  pareto.2 <- logical(length(x))
  x.sort <- sort(x)
  y.sort <- y[order(x)]
  y.min <- max(y)
  for(i in 1:length(x.sort)) {
    if(pareto.2[i] <- y.sort[i] <= y.min) y.min <- y.sort[i]
  }    
} )
# user  system elapsed 
# 0.036   0.000   0.035 
原件:

pareto = 1:length(x)
system.time(
  for(i in 1:length(x)){
    cond1 = y[i]!= min(y[which(x==x[i])])
    cond2 = x[i]!= min(x[which(y==y[i])])
    for(n in 1:length(x)){
      if((x[i]>x[n]  &  y[i]>y[n]) | (x[i]==x[n] & cond1) | (y[i]==y[n] & cond2)){
        pareto[i] = NA
        break
      }
    }
  }  
)
# user  system elapsed 
# 5.32    0.00    5.33          
显示这两种方法会产生相同的结果(有点棘手,因为我需要将pareto.2重新排序为原始的
x
):

跟随@BrodieG

system.time( {
    d = data.frame(x,y)
    D = d[order(d$x,d$y,decreasing=FALSE),]
    front = D[which(!duplicated(cummin(D$y))),]
} )

   user  system elapsed 
   0.02    0.00    0.02 

这是0.86/0.02=43倍快!

我实际上从其他人的帖子中找到了一种更快的方法来解决这个问题,尽管我喜欢for循环的可读性。要查看答案,请查看我现在问另一个问题的地方。@StatMan,在答案中查看新版本。似乎与您找到的另一个类似。在C++中帕累托边界(SkyLo线)的实现
all.equal(pareto.2[match(1:length(x), order(x))], !is.na(pareto))
# [1] TRUE
system.time( {
    d = data.frame(x,y)
    D = d[order(d$x,d$y,decreasing=FALSE),]
    front = D[which(!duplicated(cummin(D$y))),]
} )

   user  system elapsed 
   0.02    0.00    0.02