R查找包含所有值的所有可能组合的最佳集合

时间:2015-12-31 11:36:38

标签: r select optimization combinations nonlinear-optimization

经过一段时间的努力,我希望有人可以帮我解决这个问题,对我来说这看起来很简单,但可能比我想象的更复杂:

我有一个包含三列的data.frame。前两个反映了五个变量的所有可能组合(1-5),最后一个"强度"组合。我查找了五行,其中包括Var1和Var2的所有值(因此值为1-5),并且在strength列中具有最高的总和。在下面的示例中,它是五行,强度为1000,因为它们具有最高的总和,并且前两列中给出了所有五个值(1-5)。

我如何最好地解决这个问题?有没有实现该任务的包?我现在发现了constrOptim()函数,我可以用它做吗?

创建示例数据帧的代码:

a <-cbind(expand.grid(seq(1,5,1),seq(1,5,1)),
          strength = c(-11, 61, 230, 118, 156, 98, 169, 306, 6, -54,   
                        207, -32, 27, 128, 101, 19, -18, 32, 153, 14, 
                        63, 136, 165, 73, 35))
a <- a[order(a$strength, decreasing=T),]

启动数据集:

 Var1 Var2 strength
 3    2      306
 3    1      230
 1    3      207
 2    2      169
 3    5      165
 5    1      156
 4    4      153
 2    5      136
 4    3      128
 4    1      118
 5    3      101
 1    2       98
 4    5       73
 1    5       63
 2    1       61
 5    5       35
 3    4       32
 3    3       27
 1    4       19
 5    4       14
 4    2        6
 1    1      -11
 2    4      -18
 2    3      -32
 5    2      -54

不理想的结果:

 Var1 Var2 strength
 3    2      306
 3    1      230
 1    3      207
 2    2      169
 3    5      165

期望的结果:

 Var1 Var2 strength
 3    2      306
 1    3      207
 5    1      156
 4    4      153
 2    5      136

2 个答案:

答案 0 :(得分:1)

Var1Var2列之间考虑一系列aggregationmerges

# MERGE MAX AGGREGATES WHERE Var COL ARE EQUAL AND NOT EQUAL
mergedf1 <- merge(aggregate(strength ~ Var1, data=a[a$Var1==a$Var2,], FUN=max), 
                  a, by=c("Var1", "strength"))
mergedf2 <- merge(aggregate(strength ~ Var1, data=a[a$Var1!=a$Var2,], FUN=max), 
                  a, by=c("Var1", "strength"))

# STACK RESULTS 
mergedf <- rbind(mergedf1, mergedf2)

# FINAL MAX AGGREGATION AND MERGE
final <- merge(aggregate(strength ~ Var2, data=mergedf, FUN=max), 
               mergedf, by=c("Var2", "strength"))
final <- final[,c("Var1", "Var2", "strength")]                    # SORT COLUMNS
final <- final[with(final, order(-strength)),]                    # SORT ROWS

# REMOVE TEMP OBJECTS
rm(mergedf1, mergedf2, mergedf)

答案 1 :(得分:1)

我不确定所提出的解决方案是否最有效,但不知何故我觉得我们必须遍历整个数据集才能找到唯一的对(例如将(Var1 = 2, Var2 = 5, strength = 136)的值更改为{{1}为了找到唯一的对,我使用了apply函数。首先让我们重新创建输入:

(Var1 = 2, Var2 = 5, strength = 1)

现在我准备一个空矩阵,我将在第一列中保留a <-cbind(expand.grid(seq(1,5,1),seq(1,5,1)), strength = c(-11, 61, 230, 118, 156, 98, 169, 306, 6, -54, 207, -32, 27, 128, 101, 19, -18, 32, 153, 14, 63, 136, 165, 73, 35)) a <- a[order(a$strength, decreasing=T),] ,在第二列中保留Var1,在第三列保留Var2

strength

接下来,我编写了一个函数,它将从有序数据集V <- matrix(nrow = 5, ncol = 3) 中获取一行,检查aVar1是否唯一,如果是,则会存储强度。

Var2

现在我在mf <- function(x){ if( !(x[1] %in% V[,1]) & !(x[2] %in% V[,2])) { i <- x[1] V[i,1] <<- x[1] V[i,2] <<- x[2] V[i,3] <<- x[3] } } 的每一行上应用该函数:

a

所需的值存储在矩阵apply(a, 1, mf)

V

有时,尽管不需要遍历完整数据集(如在给出的示例中),但是一旦找到唯一对,我们希望能够打破循环。为此,我们可以使用V [,1] [,2] [,3] [1,] 1 3 207 [2,] 2 5 136 [3,] 3 2 306 [4,] 4 4 153 [5,] 5 1 156 循环。这是代码:

for

希望这会有所帮助,或至少会带来改善。