我有一个包含五个项目的向量。
my_vec <- c("a","b","a","c","d")
如果我想将这些值重新排列到一个新的向量(shuffle)中,我可以使用sample():
shuffled_vec <- sample(my_vec)
简单 - 但是sample()函数只给我一个可能的洗牌。 如果我想知道所有可能的混洗组合怎么办?各种“combn”函数似乎没有帮助,expand.grid()给了我所有可能的组合< em> with 替换,当我需要它时没有替换。什么是最有效的方法?
请注意,在我的向量中,我有两次值“a” - 因此,在返回的混洗向量集中,它们都应该在集合中都有两次“a”。
答案 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