2015-09-04 5 views
2

Моя цель состоит в создании уникального списка комбинаций, когда мы знаем, что может существовать аналогичная комбинация переменных, поскольку часть используемого множества имеет повторяющиеся значения. Таким образом, проблема, которую я пытаюсь решить, заключается в получении всех комбинаций без замены на отдельные элементы. Решение должно быть общим (т. Е. Работает для любого набора из N элементов с значениями M различных элементов. Таким образом, решение должно работать с 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 

Если Х = Y, то мы имеем:

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

Таким образом, у нас есть две комбинации, которые не являются «уникальными»: (X) и (XZ).

Итак, список, что я хочу это:

X X Z 
X Z 
Z 
X X 
X 

Edit: Добавлен случай, когда 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 = Х = 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 

End Edit

Использование 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] 
} 

Чтобы изменить его так, чтобы Переменная1 = Переменная2, я просто использовать :

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

Любые предложения относительно того, как я мог бы перейти от исходной матрицы к более поздней матрице?

Особенно, если у нас есть больше переменных, которые сопряжены?

E.g. comb.mat (4), с: (Var1 = Var2, Var3 = Var4) или (Var1 = Var2 = Var3, Var4)

+0

Я думаю- см. '? Combn' –

+0

' combn' не дает правильной структуры, например. combn (c ("X", "Y", "Z"), 2) => [["X", "X", "Y"], ["Y", "Z", " Z "]] Обратите внимание, что X повторяется, даже если он поставляется только один раз. Аналогично, Z повторяется. – coatless

+0

Может помочь показать результат, который вы ищете в обновленном примере с помощью 'comb.mat (4)' – Whitebeard

ответ

2

У этого есть все комбинации, я считаю.

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 

Edit: Думаю, что это работает для нескольких эквивалентных variables- не мог понять метод без 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 
+0

Я не уверен, что это решение может масштабироваться, поскольку оно зависит от данных, разделенных на переменную. А также их ограничение, которое добавляется в отношении того, сколько нечетких переменных вы можете иметь (например, Var1 = Var2, Var3 = Var4) – coatless

+0

Вы можете использовать 'split' с несколькими переменными; например 'split (m, m [, c (" Var3 "," Var4 ")])'. В моем отредактированном сообщении я в основном применял свою функцию рекурсивно для нескольких пар переменных – Whitebeard

Смежные вопросы