如何完全洗牌R中的列

How to completely shuffle column in R

我想随机打乱 R 中的一列数字,并作为新列追加 3 次。但我希望每次都将每个元素改组到一个新行。 假设如果 1 为 c2 转到 r3,它不能为 c3

到达 r1 或 r3
sample <- 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 generated\n', 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