【问题标题】:R Find best set of all possible combinations that includes all valuesR找到包括所有值的所有可能组合的最佳集合
【发布时间】:2015-12-31 11:36:37
【问题描述】:

经过相当多的谷歌努力,我希望有人可以帮助我解决这个问题,这对我来说似乎很简单,但可能比我想象的要复杂:

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

【问题讨论】:

  • 你能显示预期的输出吗?
  • 问题出在“所有变量都在第一列和第二列中使用......”。这是什么意思?
  • 最终解决方案应该有五行。前两列 (v1,v2) 都应该包含从 1 到 5 的所有值。这说明清楚了吗?我可以发布一个我以后知道解决方案的示例。这个例子是随机的,因此我不知道解决方案。谢谢!
  • 如果你不知道答案应该是什么样子,你怎么知道它是否正确?
  • 看来问题是如何排序并取前5个结果: set.seed(4444) a

标签: r select optimization combinations nonlinear-optimization


【解决方案1】:

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

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)

接下来我编写一个函数,从有序数据集a 中获取一行,检查Var1Var2 是否唯一,如果是,将存储强度。

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 循环。代码如下:

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),]

V <- matrix(nrow=5,ncol=3)
for (i in 1:nrow(a)) {
    if( sum(is.na(V[,1])) == 0)
        break
    if( !(a[i,1] %in% V[,1]) & !(a[i,2] %in% V[,2])) {
        j <- a[i,1]
        V[j,1] <- a[i,1]
        V[j,2] <- a[i,2]
        V[j,3] <- a[i,3]
    }
}

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

【讨论】:

    【解决方案2】:

    考虑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)
    

    【讨论】:

    • 谢谢,但我必须重新表述问题,以反映我的问题。请参阅上面的新所需输出。
    • 发生了什么变化?我刚刚使用了您的数据框示例并运行了上面的代码。最终结果符合您想要的结果。只需删除 row.names() 行。
    • 嗨,对不起,我的例子不好。我做了一个新的。问题是每个值 (1-5) 应该在 Var1 和 Var2 列中可用。如果我只是按强度排序的话,这个不一定给出。虽然在特定情况下是可能的。
    • 使用aggregate()merge() 的组合查看更新。
    猜你喜欢
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    相关资源
    最近更新 更多