繁体   English   中英

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

[英]R Find best set of all possible combinations that includes all values

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

我有一个包含三列的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

考虑一下Var1Var2列之间的一系列聚合合并

# 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)

我不确定提出的解决方案是否是最有效的解决方案,但是我觉得我们必须遍历整个数据集才能找到唯一的对(例如,更改(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]
    }
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM