有人会碰巧知道如何在R中编写数据集的混编吗,例如,如果我在一个数据帧中有25个数字(5行x 5列),并且我分别混洗25次,则每个数字都会出现在每个位置一次?
因此,这并不是完全随机的,至少在第一次洗牌之后并非如此,因为随着每次洗牌,任何数量的潜在位置都会减少。
谢谢!
答案 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矩阵。