存在重复项时生成唯一组合

Generate Unique Combinations When Duplicates Exist

我的目标是在我们知道可能存在类似的变量组合时生成一个唯一的组合列表,因为正在操作的集合的一部分具有重复值。因此,我要解决的问题是在不替换非不同项目的情况下获得所有组合。 解决方案需要是通用的(即适用于任何具有不同项目的 M 值的 N 元素集。因此,解决方案应该适用于 N = 4,M = 2 和(Var1 = Var2,Var3 = Var4 ) 或 (Var1 = Var2 = Var3, Var4) 等)。 作为我尝试做的一个简单示例,采用三个变量:X、Y、Z

经典组合是:

X    Y    Z
Y    Z
X    Z
Z
X    Y 
Y  
X

如果我们让 X = Y,那么我们有:

X    X    Z
X    Z
X    Z
Z
X    X
X
X

因此,我们有两个不是 "unique" 的组合:(X) 和 (X Z)。

所以,我想要的列表是:

X    X    Z
X    Z
Z
X    X
X

编辑:根据@Sam Thomas

的建议添加了 N=4 时的情况

如果我们将其展开为 N=4,我们有:W,X,Y,Z

W    X    Y    Z
X    Y    Z
W    Y    Z
Y    Z
W    X    Z
X    Z
W    Z
Z
W    X    Y
X    Y
W    Y
Y
W    X
X
W

在这里,我们可以有 M=2 个不同的元素,其形式为:(W=X, Y=Z), (X=Z,W=Y), (X=Y,W=Z), (W = X = Y,Z),(W = Z = Y,X),(W = Z = X,Y),或(X = Y = Z,W)。

在 (W=X, Y=Z) 的情况下,我们有:

W    W    Y    Y
W    Y    Y
W    Y    Y
Y    Y
W    W    Y
W    Y
W    Y
Y
W    W    Y
W    Y
W    Y
Y
W    W
W
W

输出应该是:

W    W    Y    Y
W    Y    Y
Y    Y
W    W    Y
W    Y
Y
W    W
W

在 (W = X = Y, Z) 的情况下,矩阵最初看起来像:

W    W    W    Z
W    W    Z
W    W    Z
W    Z
W    W    Z
W    Z
W    Z
Z
W    W    W
W    W
W    W
W
W    W
W
W

所需的输出将是:

W    W    W    Z
W    W    Z
W    Z
Z
W    W    W
W    W
W

结束编辑

使用 R,我已经有办法以二进制矩阵形式生成所有可能组合的列表:

comb.mat = function(n){
     c = rep(list(1:0), n)
     expand.grid(c)
}

comb.mat(3)

这给出:

  Var1 Var2 Var3
1    1    1    1
2    0    1    1
3    1    0    1
4    0    0    1
5    1    1    0
6    0    1    0
7    1    0    0
8    0    0    0

如果我们考虑Var1 = Var2,这个结构就会有冗余。例如第 (2,3) 行和第 (6,7) 行代表同一个对象。因此,无冗余版本将是:

  Var1 Var2 Var3
1    1    1    1
2    0    1    1
4    0    0    1
5    1    1    0
6    0    1    0
8    0    0    0

要添加类似于初始结构的 "variable" 值,我使用:

nvars = ncol(m)

for(i in 1:nvars){
  m[m[,i]==1,i] = LETTERS[22+i]
}

要修改它使 Var1 = Var2,我只使用:

  m[m[,i]=="Y",i] = "X"

关于如何从初始矩阵移动到后来矩阵的任何建议?

特别是如果我们有更多配对的变量?

例如comb.mat(4),其中:(Var1 = Var2, Var3 = Var4) 或 (Var1=Var2=Var3, Var4)

我相信这有所有的组合。

m <- comb.mat(3)

res <- lapply(split(m, m$Var3), function(x, vars=c("Var1", "Var2")) {
   x[Reduce(`==`, x[vars]) | cumsum(Reduce(xor, x[vars])) == 1, ]
})

do.call(rbind, res)
    Var1 Var2 Var3
0.5    1    1    0
0.6    0    1    0
0.8    0    0    0
1.1    1    1    1
1.2    0    1    1
1.4    0    0    1

编辑: 认为这适用于多个等效变量 - 无法找出没有 for 循环的方法。我确定 Reduce 有某种方法。

认为这给出了正确的结果组合,但如果不是这样请告诉我,因为已经很晚了,我有点累了。

remove_dups <- function(m, vars) {
  for (k in 1:length(vars)) {
      res <- lapply(split(m, m[, !names(m) %in% vars[[k]]]), function(x, vn=vars[[k]]) {
        x[Reduce(`==`, x[vn]) | cumsum(Reduce(xor, x[vn])) == 1, ]
     })
     m <- do.call(rbind, res)
  }
  m
}

 m <- comb.mat(4)
 remove_dups(m, list(vars=c("Var1", "Var2"), vars=c("Var3", "Var4")))

           Var1 Var2 Var3 Var4
0.0.0.0.16    0    0    0    0
0.0.1.0.12    0    0    1    0
0.0.1.1.4     0    0    1    1
0.1.0.0.14    0    1    0    0
0.1.1.0.10    0    1    1    0
0.1.1.1.2     0    1    1    1
1.1.0.0.13    1    1    0    0
1.1.1.0.9     1    1    1    0
1.1.1.1.1     1    1    1    1