循环遍历 R 中的一组项目

Loop through a set of items in R

我正在尝试模拟线性规划问题。该模型有一个 obj 函数和一些约束。在本例中,我引入了 2 个从正态分布中随机抽取的值。

然后我使用 for 循环模拟优化模型 10.000 次。我知道使用 for 循环是不好的 R 实践,但在这种情况下我不关心速度。

#List of 10000 random, normally distributed observations:
Demand = rnorm(10000, mean=5, sd=2.5)
Demand

Performance = rnorm(10000, mean=100, sd=6)
Performance

Optimas = NULL

#combined_list = c(Demand, Performance)

for (i in Performance){
    op <- OP(objective = c(2.5, 4, i),               #Performance value[i]: works fine 
             L_constraint(L = matrix(c(1, 0, 0,      #LHS
                                       0, 1, 0,       
                                       0, 0, 1),      
                                      ncol=3, nrow = 3, 
                                      byrow = TRUE), 
                          dir = c("<=", "<=", "<="), 
                          rhs = c(50, 70, Demand)),  #Demand value[i]: should go here
              maximum = TRUE,
              types = c("B", "I", "I"))  

    Optima <- ROI_solve(op, solver = "glpk") #solve
    print(Optima)
    print(i)
    Optimas = rbind(Optimas, Optima)
}


Optimas <- as.data.frame(Optimas)
Optimas$objval <- as.numeric(Optimas$objval)
hist(Optimas$objval)

如上所示,我的循环只通过一个变量(性能),我希望将需求向量中行(i)的需求值与性能值同时放入模型中对于性能向量中的第 (i) 行。

总的来说 objective 是对 LP 模型进行 10.000 次模拟,其中性能值和需求值只出现一次(因为我已有的循环之外的另一个循环将产生两个列表的笛卡尔积)。

请注意,您的 PerformanceDemand 向量包含的元素数量完全相同。因此,您可以简单地遍历向量索引并使用各自的索引值来提取相关元素。

我无法 运行 你的示例代码,因为我不确定你的 OP 函数使用的是哪个优化包。作为示例,我将定义一个简单的 dummyFunction,它将性能和需求值作为输入,如下所示:

dummyFunction <- function(perf, dem){ return (perf+dem)}

在您的特定用例中,dummyFunction 将包含优化逻辑。接下来,您可以通过迭代向量索引来获得所需的解决方案,如下所示:

Optimas = vector(mode="numeric", length=length(Performance))
for(idx in 1:length(Performance)){
  Optimas[idx] <- dummyFunction(Performance[idx], Demand[idx])
}

或者,您可以通过将优化逻辑放在 for 循环中来避免函数定义。 更多 "R like solution" 考虑使用 sapply / lapply 类型函数:

Optimas <- sapply(1:length(Performance), function(idx) dummyFunction(Performance[idx], Demand[idx]))

请注意,在此特定示例中,您还可以执行以下操作:

Optimas <- dummyFunction(Performance, Demand)

最后,如果性能成为问题,请考虑使用 foreachdoparallel 包来 运行 同时优化多核:

library(doParallel)
library(foreach)
nrCores <- detectCores()
cl <- makeCluster(nrCores); registerDoParallel(cl)
clusterExport(cl,c("Demand", "Performance", "dummyFunction"), envir=environment())
Optimas <- foreach(idx=1:length(Performance), .combine="rbind") %dopar%{
  dummyFunction(Performance[idx], Demand[idx])
}
stopCluster(cl)

考虑一个 mapply() 方法,apply 函数迭代多个 lists/vectors 传递相应的元素。首先将所有操作包装在一个函数中,然后在 mapply() 中调用它,为向量传递两个参数。最后,使用 lapply() 转置为一长串数据帧,这些数据帧与 do.call(rbind...).

行绑定
Performance = rnorm(10000, mean=100, sd=6)
Demand = rnorm(10000, mean=5, sd=2.5)

optimizefct <- function(p, d){
  op <- OP(objective = c(2.5, 4, p),               # Performance 
           L_constraint(L = matrix(c(1, 0, 0,      # LHS
                                     0, 1, 0,       
                                     0, 0, 1),      
                                   ncol=3, nrow = 3, 
                                   byrow = TRUE), 
                        dir = c("<=", "<=", "<="), 
                        rhs = c(50, 70, d)),       # Demand
           maximum = TRUE,
           types = c("B", "I", "I"))  

  Optima <- ROI_solve(op, solver = "glpk") #solve
  print(Optima)
  print(i)

  return(Optima)
}

# WIDE FORMAT
dfList <- mapply(optimizefct, Performance, Demand)

# LONG FORMAT
dfList <- lapply(1:10000, function(i) data.frame(dfList[,i]))

# BIND TO FINAL DF
Optimas <- do.call(rbind, dfList)
Optimas$objval <- as.numeric(Optimas$objval)