我想随机洗牌R中的一列数字,并作为新列追加三次。但是我想让每个元素每次都洗牌到新行。如果c1指向r3,那么c3
就不可能指向r1或r3sample <- data.frame(1:4)
基本上产生了类似这样的东西,但我想用在更大的数据中,
c1是原始的
||||||c1| c2 |c3 |c4
---------------
r1 | 1 | 4 | 3 | 2
r2 | 2 | 1 | 4 | 3
r3 | 3 | 2 | 1 | 4
r4 | 4 | 3 | 2 | 1
有趣的问题。这是一个不太优雅的解决方案,它解决了数字1到4,但适用于任何初始值集。
它依次构建每个列。在每一步中,它首先随机洗牌第一列中的数字。然后它确保没有逐行匹配,所以就像你说的,如果1对c2到r3,它不能对c3到r1或r3。
library(dplyr)
initial_values <- 1:4
cs <- tibble(c1 = initial_values,
c2 = 1,
c3 = 1,
c4 = 1)
while(any(cs$c1 == cs$c2)){
cs <- cs %>%
mutate(c2 = sample(c1, length(c1)))
}
while(any(cs$c3 == cs$c2 | cs$c3 == cs$c1)){
cs <- cs %>%
mutate(c3 = sample(c1, length(c1)))
}
while(any(cs$c4 == cs$c3 | cs$c4 == cs$c2 | cs$c4 == cs$c1)){
cs <- cs %>%
mutate(c4 = sample(c1, length(c1)))
}
结果如下:
# A tibble: 4 x 4
c1 c2 c3 c4
<int> <int> <int> <int>
1 1 4 2 3
2 2 3 1 4
3 3 2 4 1
4 4 1 3 2
只要稍加思考,我相信您可以将其扩展为适用于任意列数的一般函数。
使用的最佳方法取决于您有多少行和列(以及c1中是否存在重复值)。
假设需要的行数多于列数(迭代),合理的方法可能是随机生成排列,丢弃任何产生重复的内容:
N = 100000
ncols = 3
sample = data.frame(c1=1:N)
orderings = data.frame(c1 = 1:N) # Initial ordering
reordering = orderings[,1]
c = 1
no_generated = 0
while (c <= ncols){
while (sum(reordering == orderings) > 0){ # check for any repetitions
print(sum(reordering == orderings))
reordering = order(runif(N)) # random reordering
no_generated = no_generated + 1
}
c = c + 1
orderings[[paste0('c',c)]] = reordering
}
cat(sprintf('%d permutations generatedn', no_generated))
print(sum(duplicated(orderings,MARGIN=2))) # Should be zero
如果行数更接近所需的列数,则更聪明的组合方法可能更好。
我可以用while循环来解决这个问题。我知道循环条件有点长,但在我的例子中,我知道我只需要3列,所以它不是太糟糕。我想如果列数未知,我需要更多的修改
data = c(1:5)
data_1 = c(1:5)
data_2 = c(1:5)
data_3 = c(1:5)
while(any(data == data_1|data == data_2|data == data_3|data_1 == data_2|data_1 == data_3|data_2 == data_3)){
data_1 = c(sample(data,5, replace = FALSE))
data_2 = c(sample(data,5, replace = FALSE))
data_3 = c(sample(data,5, replace = FALSE))
}
df = data.frame(data,data_1,data_2,data_3)
df