【问题标题】:Generate Unique Combinations When Duplicates Exist存在重复项时生成唯一组合
【发布时间】:2015-11-30 22:31:36
【问题描述】:

当我们知道可能存在类似的变量组合时,我的目标是生成一个唯一的组合列表,因为正在操作的部分集合具有重复值。因此,我要解决的问题是在不替换非不同项目的情况下获得所有组合。 解决方案需要是通用的(即适用于具有 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

因此,我们有两个不“唯一”的组合:(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

要添加类似于初始结构的“变量”值,我使用:

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)

【问题讨论】:

  • 我认为-见?combn
  • combn 没有给出正确的结构,例如组合(c(“X”,“Y”,“Z”),2)=>[[“X”,“X”,“Y”],[“Y”,“Z”,“Z”]]请注意,即使只提供了一次 X,它也会重复。同样,Z 也是重复的。
  • 可能有助于在comb.mat(4)的更新示例中显示您正在寻找的结果
  • 完成!感谢@SamThomas 的建议

标签: r combinations


【解决方案1】:

我相信这有所有的组合。

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

【讨论】:

  • 我不确定这个解决方案是否能够扩展,因为它依赖于在变量上拆分的数据。它们也是一个关于可以拥有多少非不同变量的约束(例如 Var1 = Var2,Var3 = Var4)
  • 您可以将split与多个变量一起使用;例如split(m, m[, c("Var3", "Var4")])。在我编辑的帖子中,我基本上将我的函数递归地应用于多对变量
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多