[英]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
# 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
获得一行,将检查Var1
和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
循环。 这是代码:
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.