2013-12-03 4 views
3

У меня есть вектор с пятью пунктами.Перемешивание вектора - все возможные результаты выборки()?

my_vec <- c("a","b","a","c","d") 

Если я хочу, чтобы переставить эти значения в новый вектор (в случайном порядке), я мог бы использовать образец():

shuffled_vec <- sample(my_vec) 

Легко - но образец() функция только дает мне одну возможно перетасовать. Что делать, если я хочу знать все возможные комбинации перетасовки? Различные функции «combn», похоже, не помогают, и expand.grid() дает мне все возможные комбинации с заменой, когда мне это нужно без замена. Каков наиболее эффективный способ сделать это?

Обратите внимание, что в моем векторе у меня есть значение «a» дважды, поэтому в наборе перетасованных векторов все они должны иметь «a» два раза в наборе.

+0

могли бы вы предоставить некоторую обратную связь с 3-х ответов, которые у вас есть сейчас? –

ответ

3

Глядя на предыдущий вопрос (R: generate all permutations of vector without duplicated elements), я вижу, что у пакета gtools есть функция. Я не мог, однако получить эту работу прямо на вектор, как, например:

permutations(n = 5, r = 5, v = my_vec) 
#Error in permutations(n = 5, r = 5, v = my_vec) : 
# too few different elements 

Вы можете адаптировать его, как например, так:

apply(permutations(n = 5, r = 5), 1, function(x) my_vec[x]) 

#  [,1] [,2] [,3] [,4] 
#[1,] "a" "a" "a" "a" ... 
#[2,] "b" "b" "b" "b" ... 
#[3,] "a" "a" "c" "c" ... 
#[4,] "c" "d" "a" "d" ... 
#[5,] "d" "c" "d" "a" ... 
1

Я думаю permn из КОМБИНАТ пакета делает то, что вы хотите

library(combinat) 
permn(my_vec) 

меньший пример

> x 
[1] "a" "a" "b" 
> permn(x) 
[[1]] 
[1] "a" "a" "b" 

[[2]] 
[1] "a" "b" "a" 

[[3]] 
[1] "b" "a" "a" 

[[4]] 
[1] "b" "a" "a" 

[[5]] 
[1] "a" "b" "a" 

[[6]] 
[1] "a" "a" "b" 

Если дубликаты проблема, которую вы могли бы сделать что-то похожее на это, чтобы избавиться от дубликатов

strsplit(unique(sapply(permn(my_vec), paste, collapse = ",")), ",") 

Или, вероятно, лучший подход к удалению дубликатов ...

dat <- do.call(rbind, permn(my_vec)) 
dat[duplicated(dat),] 
2

отмечая, что ваши данные эффективно 5 уровней от 1 до 5, закодированные как «a», «b», «a», «c» и «d», я пошел искать способы получить перестановки чисел 1-5, а затем переназначить эти до уровней, которые вы используете.

Начнем с ввода данных:

my_vec <- c("a","b","a","c","d") # the character 
my_vec_ind <- seq(1,length(my_vec),1) # their identifier 

Чтобы получить перестановки, я применил функцию, заданную на Generating all distinct permutations of a list in R:

permutations <- function(n){ 
    if(n==1){ 
    return(matrix(1)) 
    } else { 
    sp <- permutations(n-1) 
    p <- nrow(sp) 
    A <- matrix(nrow=n*p,ncol=n) 
    for(i in 1:n){ 
     A[(i-1)*p+1:p,] <- cbind(i,sp+(sp>=i)) 
    } 
    return(A) 
    } 
} 

Во-первых, создать data.frame с перестановками:

tmp <- data.frame(permutations(length(my_vec))) 

У вас теперь есть фрейм данных tmp из 120 ro WS, где каждая строка представляет собой уникальную перестановка чисел, 1-5:

>tmp 
    X1 X2 X3 X4 X5 
1 1 2 3 4 5 
2 1 2 3 5 4 
3 1 2 4 3 5 
... 
119 5 4 3 1 2 
120 5 4 3 2 1 

Теперь вам нужно переназначить их к струнам вы имели.Вы можете переназначить их, используя вариации на тему gsub(), предложенной здесь: R: replace characters using gsub, how to create a function?

gsub2 <- function(pattern, replacement, x, ...) { 
    for(i in 1:length(pattern)) 
    x <- gsub(pattern[i], replacement[i], x, ...) 
    x 
} 

gsub() не будет работать, потому что у вас есть более одного значения в массиве замены.

Вам также нужна функция, которую вы можете позвонить, используя lapply(), чтобы использовать функцию gsub2() для каждого элемента вашего tmp data.frame.

remap <- function(x, 
       old, 
       new){ 
    return(gsub2(pattern = old, 
       replacement = new, 
       fixed = TRUE, 
       x = as.character(x))) 
} 

Практически там. Мы делаем отображение, как это:

shuffled_vec <- as.data.frame(lapply(tmp, 
          remap, 
          old = as.character(my_vec_ind), 
          new = my_vec)) 

, который может быть упрощена ...

shuffled_vec <- as.data.frame(lapply(data.frame(permutations(length(my_vec))), 
          remap, 
          old = as.character(my_vec_ind), 
          new = my_vec)) 

.. если вы чувствуете потребность.

Это дает Вам необходимый ответ:

> shuffled_vec 
    X1 X2 X3 X4 X5 
1 a b a c d 
2 a b a d c 
3 a b c a d 
... 
119 d c a a b 
120 d c a b a 
+0

Несмотря на то, что ОП не ответил, у меня очень похожая проблема, и я нашел это очень полезным. Однако у меня есть еще один дополнительный вопрос ... Этот вопрос имеет только 5 элементов, но для ситуаций, когда есть много других элементов, скорость, очевидно, является проблемой. Кроме того, для большинства приложений такого типа нам нужно всего лишь 10 000 возвращенных перестановок. Можно ли изменить этот код, чтобы вернуть до 10 000 уникальных перм? – jalapic

+0

Если вы хотите 10 000 случайных выборок, используйте что-то вроде 'tmp <- tmp [sample (1: NROW (tmp), 10000, replace = F),]' –

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