2012-05-09 4 views
2

Я хотел бы сгенерировать все комбинации двух векторов, учитывая два ограничения: из первого вектора никогда не может быть больше трех символов, и всегда должно быть не менее одного символа от второго вектора. Я также хотел бы изменить окончательное количество символов в комбинации.R - генерировать все комбинации из 2 векторов заданных ограничений

Например, вот два вектора:

vec1=c("A","B","C","D") 
vec2=c("W","X","Y","Z") 

Скажем, я хотел 3-х символов в комбинации. Возможными приемлемыми перестановками могут быть: "A" "B" "X" или "A" "Y" "Z". Неприемлемой перестановкой будет: "A" "B" "C", поскольку не существует хотя бы одного символа от vec2.

Теперь скажите, что мне понадобилось 5 символов в комбинации. Возможными приемлемыми перестановками могут быть: "A" "C" "Z" "Y" или "A" "Y" "Z" "X". Неприемлемой перестановкой будет: "A" "C" "D" "B" "X", так как есть 3 символа от vec2.

Я полагаю, что я мог бы использовать expand.grid для создания всех комбинаций, а затем как-то подмножества, но должен быть более простой способ. Заранее спасибо!

ответ

5

Я не уверен, Wheter это проще, но вы можете оставить далеко перестановки, которые не удовлетворяют заданные условия ти этой стратегии:

  1. генерируют все комбинации из vec1, которые являются приемлемыми.

  2. генерирует все комбинации из vec2, которые являются приемлемыми.

  3. генерировать все комбинации, принимающие одно решение от 1. + одно решение от 2. Здесь я бы сделал фильтрацию с условием 3 после этого.

  4. (если вы ищете комбинации, все готово, иначе :) произведите все перестановки букв в каждом результате.

Теперь давайте

vec1 <- LETTERS [1:4] 
vec2 <- LETTERS [23:26] 

## lists can eat up lots of memory, so use character vectors instead. 
combine <- function (x, y) 
    combn (y, x, paste, collapse = "") 

res1 <- unlist (lapply (0:3, combine, vec1)) 
res2 <- unlist (lapply (1:length (vec2), combine, vec2)) 

теперь мы имеем:

> res1 
[1] "" "A" "B" "C" "D" "AB" "AC" "AD" "BC" "BD" "CD" "ABC" 
[13] "ABD" "ACD" "BCD" 
> res2 
[1] "W" "X" "Y" "Z" "WX" "WY" "WZ" "XY" "XZ" "YZ" 
[11] "WXY" "WXZ" "WYZ" "XYZ" "WXYZ" 

res3 <- outer (res1, res2, paste0) 
res3 <- res3 [nchar (res3) == 5] 

Так вот вы:

> res3 
[1] "ABCWX" "ABDWX" "ACDWX" "BCDWX" "ABCWY" "ABDWY" "ACDWY" "BCDWY" "ABCWZ" 
[10] "ABDWZ" "ACDWZ" "BCDWZ" "ABCXY" "ABDXY" "ACDXY" "BCDXY" "ABCXZ" "ABDXZ" 
[19] "ACDXZ" "BCDXZ" "ABCYZ" "ABDYZ" "ACDYZ" "BCDYZ" "ABWXY" "ACWXY" "ADWXY" 
[28] "BCWXY" "BDWXY" "CDWXY" "ABWXZ" "ACWXZ" "ADWXZ" "BCWXZ" "BDWXZ" "CDWXZ" 
[37] "ABWYZ" "ACWYZ" "ADWYZ" "BCWYZ" "BDWYZ" "CDWYZ" "ABXYZ" "ACXYZ" "ADXYZ" 
[46] "BCXYZ" "BDXYZ" "CDXYZ" "AWXYZ" "BWXYZ" "CWXYZ" "DWXYZ" 

Если вы предпочитаете результаты разделить на отдельные буквы :

res <- matrix (unlist (strsplit (res3, "")), nrow = length (res3), byrow = TRUE) 
> res 
     [,1] [,2] [,3] [,4] [,5] 
[1,] "A" "B" "C" "W" "X" 
[2,] "A" "B" "D" "W" "X" 
[3,] "A" "C" "D" "W" "X" 
[4,] "B" "C" "D" "W" "X" 

(надрез)

[51,] "C" "W" "X" "Y" "Z" 
[52,] "D" "W" "X" "Y" "Z" 

Какие ваши комбинации.

+0

Хм, интересное решение! Мне просто интересно ... если записи имеют> 1 символ (поэтому вместо 'vec = letters [1: 3]', 'vec = month.имя [1: 4] ') как выбрать комбинации с 3 записями (очевидно, nchar не будет работать) – jslefche

+0

@jslefche: Я вижу две возможности: либо идти по спискам, либо сначала придерживаться букв (и их оскорблять) как индикаторы уровня фактора), и как только у вас есть ваши комбинации, конвертируйте буквы в месяцы – cbeleites

+0

@beleites: я использовал 'strtrim' для ограничения количества символов в каждом векторе и использовал их для создания комбинаций – jslefche

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