随机播放R中的数据帧

时间:2019-11-13 16:16:16

标签: r dataframe shuffle

有人会碰巧知道如何在R中编写数据集的混编吗,例如,如果我在一个数据帧中有25个数字(5行x 5列),并且我分别混洗25次,则每个数字都会出现在每个位置一次?

因此,这并不是完全随机的,至少在第一次洗牌之后并非如此,因为随着每次洗牌,任何数量的潜在位置都会减少。

谢谢!

2 个答案:

答案 0 :(得分:2)

我将在3 x 3的数据集中演示该解决方案。我要做的第一件事是将data.frame转换为矩阵,以便能够轻松应用排列。

假设我们有一个3x3矩阵:

set.seed(1)
m <- matrix(sample(1:100, 9), nrow = 3)
m
#>      [,1] [,2] [,3]
#> [1,]   68   34   14
#> [2,]   39   87   82
#> [3,]    1   43   59

然后可以通过数字1到9的排列来定义每个随机播放。

shuffle <- c(9, 4, 7, 1, 8, 3, 2, 5, 6)
matrix(m[shuffle], nrow = 3)
#>      [,1] [,2] [,3]
#> [1,]   59   68   39
#> [2,]   34   82   87
#> [3,]   14    1   43

因此,我们的任务是生成9个这样的排列,其中每个数字在每个位置上均出现一次。例如。先进行c(9, 4, 7, 1, 8, 3, 2, 5, 6)洗牌,然后再进行c(9, 2, 7, 3, 8, 5, 4, 6, 1)的处理,因为9已经排在第一,第三和第七在第五。

基本上,我们需要的是9 x 9 latin square。幸运的是,有一个用于处理此类事情的程序包:

library(magic)
#> Loading required package: abind
set.seed(1)
shuffles_matrix <- rlatin(9)
shuffles_matrix
#>       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
#>  [1,]    6    5    4    2    3    9    8    1    7
#>  [2,]    4    2    7    6    9    8    1    3    5
#>  [3,]    8    3    1    5    2    7    9    4    6
#>  [4,]    5    1    9    7    6    2    4    8    3
#>  [5,]    3    6    5    1    8    4    7    9    2
#>  [6,]    9    7    8    3    1    6    5    2    4
#>  [7,]    7    9    3    4    5    1    2    6    8
#>  [8,]    2    8    6    9    4    5    3    7    1
#>  [9,]    1    4    2    8    7    3    6    5    9

现在,我们可以将该正方形的每一行视为原始3x3矩阵的混洗:

shuffles <- split(shuffles_matrix, 1:9)
shuffles
#> $`1`
#> [1] 6 5 4 2 3 9 8 1 7
#> 
#> $`2`
#> [1] 4 2 7 6 9 8 1 3 5
#> 
#> $`3`
#> [1] 8 3 1 5 2 7 9 4 6
#> 
#> $`4`
#> [1] 5 1 9 7 6 2 4 8 3
#> 
#> $`5`
#> [1] 3 6 5 1 8 4 7 9 2
#> 
#> $`6`
#> [1] 9 7 8 3 1 6 5 2 4
#> 
#> $`7`
#> [1] 7 9 3 4 5 1 2 6 8
#> 
#> $`8`
#> [1] 2 8 6 9 4 5 3 7 1
#> 
#> $`9`
#> [1] 1 4 2 8 7 3 6 5 9

这是我们将这些混洗应用于矩阵的方式:

library(purrr)
shuffles %>% 
  map(~matrix(m[.], nrow = 3))
#> $`1`
#>      [,1] [,2] [,3]
#> [1,]   43   39   82
#> [2,]   87    1   68
#> [3,]   34   59   14
#> 
#> $`2`
#>      [,1] [,2] [,3]
#> [1,]   34   43   68
#> [2,]   39   59    1
#> [3,]   14   82   87
#> 
#> $`3`
#>      [,1] [,2] [,3]
#> [1,]   82   87   59
#> [2,]    1   39   34
#> [3,]   68   14   43
#> 
#> $`4`
#>      [,1] [,2] [,3]
#> [1,]   87   14   34
#> [2,]   68   43   82
#> [3,]   59   39    1
#> 
#> $`5`
#>      [,1] [,2] [,3]
#> [1,]    1   68   14
#> [2,]   43   82   59
#> [3,]   87   34   39
#> 
#> $`6`
#>      [,1] [,2] [,3]
#> [1,]   59    1   87
#> [2,]   14   68   39
#> [3,]   82   43   34
#> 
#> $`7`
#>      [,1] [,2] [,3]
#> [1,]   14   34   39
#> [2,]   59   87   43
#> [3,]    1   68   82
#> 
#> $`8`
#>      [,1] [,2] [,3]
#> [1,]   39   59    1
#> [2,]   82   34   14
#> [3,]   43   87   68
#> 
#> $`9`
#>      [,1] [,2] [,3]
#> [1,]   68   82   43
#> [2,]   34   14   87
#> [3,]   39    1   59

答案 1 :(得分:1)

我认为Iaroslav的回答很好。我使用了一些不同的函数来基本上完成相同的事情,所以我想我会共享一些其他代码。基本上,我还创建了一个拉丁方形字体,但是我没有意识到这是名称。我是这么做的

roll <- function(x, i) {
  if (i==0) return(x)
  c(x[-(1:i)], x[1:i])
}
m <- sapply(0:24, function(i) roll(1:25, i))

在这里我只使用数字1:25。它创建一个矩阵,其中每一行或每一列都是一组索引,可用于置换您的值。如果看起来过于井井有条,您还可以使用另一个辅助函数来对矩阵的行和列进行混洗

shuffle_mat <- function(x, N=50, margin=c(1,2)) {
  mg <- sample(margin, N, replace=TRUE)
  n_row_swap = sum(mg==1)
  sr <- replicate(n_row_swap, sample.int(nrow(x), 2))
  for(i in 1:ncol(sr)) {
    x[sr[,i],]<-x[rev(sr[,i]),]
  }
  n_col_swap = sum(mg==2)
  sc <- replicate(n_col_swap, sample.int(ncol(x), 2))
  for(i in 1:ncol(sc)) {
    x[,sc[,i]]<-x[,rev(sc[,i])]
  }
  x
}    
rr <- shuffle_mat(m)

然后再次可以将这些行/列中的每一个都整形为5x5矩阵。