改组矢量 - 样本()的所有可能结果?

时间:2013-12-03 03:27:30

标签: r shuffle sampling

我有一个包含五个项目的向量。

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

如果我想将这些值重新排列到一个新的向量(shuffle)中,我可以使用sample():

shuffled_vec <- sample(my_vec)

简单 - 但是sample()函数只给我一个可能的洗牌。 如果我想知道所有可能的混洗组合怎么办?各种“combn”函数似乎没有帮助,expand.grid()给了我所有可能的组合< em> with 替换,当我需要它时没有替换。什么是最有效的方法?

请注意,在我的向量中,我有两次值“a” - 因此,在返回的混洗向量集中,它们都应该在集合中都有两次“a”。

3 个答案:

答案 0 :(得分: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 :(得分:3)

我认为combinat包中的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 :(得分:3)

注意到你的数据实际上是1-5级的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)))

您现在拥有120行的数据框tmp,其中每一行都是数字的唯一排列,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() data.frame的每个元素上使用tmp功能。

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