在子阵列之间移动行

时间:2018-01-05 00:01:57

标签: r sample

我有许多子数组,比如说2(为简单起见),每个都有相同数量的行和列。子阵列中的每个点都被[1,10]中的数字占据。

我想要做的是根据一些移动速率m = [0,1]在子阵列之间随机移动行。 m = 0对应于没有移动,而m = 1意味着可以移动所有子阵列中的任何行。

我从以下方面获取灵感:

How to swap a number of the values between 2 rows in R

但我的问题与此有点不同。我知道这里需要sample()。

有没有简单的方法来实现这个目标?

这不行,但我相信无论如何我都在正确的轨道上。

m <- 0.2

 a <- array(dim = c(5, 5, 2)) # 5 rows, 5 columns, 2 subarrays

res <- rep(sample(nrow(a), size = ceiling(nrow(a)*m), replace = FALSE)) # sample 20% of rows from array a. 

感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

如果您可以使用matrix(2-dim array),则会更加轻松。

set.seed(2)
m <- 0.2
d <- c(10, 4)
a <- array(sample(prod(d)), dim = d)
a
#       [,1] [,2] [,3] [,4]
#  [1,]    8   17   14    1
#  [2,]   28   37   40   26
#  [3,]   22   38   16   29
#  [4,]    7   35    3   32
#  [5,]   34   11   23    4
#  [6,]   36   33   19   31
#  [7,]    5   24   30   13
#  [8,]   39    6   27   25
#  [9,]   15   10   12    9
# [10,]   18    2   21   20

(我将把种子再次设置为方便的东西给我一些“有趣”的东西。)

set.seed(2)
ind <- which(runif(d[1]) < m)
ind
# [1] 1 4 7

将第一个随机性runifm进行比较,并生成可能更改的索引。下面的第二个随机性sample采用这些索引并可能重新排序它们。 (在这种情况下,它将“1,4,7”重新排序为“4,1,7”,这意味着可能改变的行中的第三行将保持不变。)

a[ind,] <- a[sample(ind),]
a
#       [,1] [,2] [,3] [,4]
#  [1,]    7   35    3   32  # <-- row 4
#  [2,]   28   37   40   26
#  [3,]   22   38   16   29
#  [4,]    8   17   14    1  # <-- row 1
#  [5,]   34   11   23    4
#  [6,]   36   33   19   31
#  [7,]    5   24   30   13  # <-- row 7, unchanged
#  [8,]   39    6   27   25
#  [9,]   15   10   12    9
# [10,]   18    2   21   20

请注意,这是概率,这意味着概率为0.2并不能保证您将交换20%(或甚至任何)的行。

(因为我猜你真的想保留你的3-dim(甚至 n -dim)array,你可以使用{{1}在aperm之间转移。)

编辑1

作为可能使用array <--> matrix的替代方法,您可以使用:

runif

更接近你的目标“20%”。由于ind <- head(sample(d[1]),size=d[1]*m) 通常不是整数,d[1]*m会默默地截断/覆盖数字,因此您将获得价格合适的赢家:最接近但不超过您所需的百分比。

编辑2

一种可逆的方法,用于将 n - 维数组转换为矩阵并再次转换回来。 警告 :虽然逻辑看起来很稳固,但我的测试只包含了几个数组。

head

如果仍存在,则反转使用array2matrix <- function(a) { d <- dim(a) ind <- seq_along(d) a2 <- aperm(a, c(ind[2], ind[-2])) dim(a2) <- c(d[2], prod(d[-2])) a2 <- t(a2) attr(a2, "origdim") <- d a2 } 属性;只要您对矩阵的修改不清除其属性,这将起作用。 (简单的行交换不会。)

"origdim"

(这两个函数应该进行更多的错误检查,例如matrix2array <- function(m, d = attr(m, "origdim")) { ind <- seq_along(d) m2 <- t(m) dim(m2) <- c(d[2], d[-2]) aperm(m2, c(ind[2], ind[-2])) } 。)

示例运行:

is.null(d)

快速展示:

set.seed(2)
dims <- 5:2
a <- array(sample(prod(dims)), dim=dims)

转型:

a[,,1,1:2,drop=FALSE]
# , , 1, 1
#      [,1] [,2] [,3] [,4]
# [1,]   23  109   61   90
# [2,]   84   15   27  102
# [3,]   68   95   83   24
# [4,]   20   53  117   46
# [5,]  110   62   43    8
# , , 1, 2
#      [,1] [,2] [,3] [,4]
# [1,]  118   25   14   93
# [2,]   65   21   16   77
# [3,]   87   82    3   38
# [4,]   92   12   78   17
# [5,]   49    4   75   80

可逆性证明:

m <- array2matrix(a)
dim(m)
# [1] 30  4
head(m)
#      [,1] [,2] [,3] [,4]
# [1,]   23  109   61   90
# [2,]   84   15   27  102
# [3,]   68   95   83   24
# [4,]   20   53  117   46
# [5,]  110   62   43    8
# [6,]   67   47    1   54

编辑3,“包装所有代码”

创建虚假数据:

identical(matrix2array(m), a)
# [1] TRUE

随机交换行。我在这里使用50%。

dims <- c(5,4,2)
(a <- array(seq(prod(dims)), dim=dims))
# , , 1
#      [,1] [,2] [,3] [,4]
# [1,]    1    6   11   16
# [2,]    2    7   12   17
# [3,]    3    8   13   18
# [4,]    4    9   14   19
# [5,]    5   10   15   20
# , , 2
#      [,1] [,2] [,3] [,4]
# [1,]   21   26   31   36
# [2,]   22   27   32   37
# [3,]   23   28   33   38
# [4,]   24   29   34   39
# [5,]   25   30   35   40
(m <- array2matrix(a))
#       [,1] [,2] [,3] [,4]
#  [1,]    1    6   11   16
#  [2,]    2    7   12   17
#  [3,]    3    8   13   18
#  [4,]    4    9   14   19
#  [5,]    5   10   15   20
#  [6,]   21   26   31   36
#  [7,]   22   27   32   37
#  [8,]   23   28   33   38
#  [9,]   24   29   34   39
# [10,]   25   30   35   40
# attr(,"origdim")
# [1] 5 4 2

(请注意,我在这里预先制作了pct <- 0.5 nr <- nrow(m) set.seed(3) (ind1 <- sample(nr, size = ceiling(nr * pct))) # [1] 2 8 4 3 9 (ind2 <- sample(ind1)) # [1] 3 2 9 8 4 m[ind1,] <- m[ind2,] m # [,1] [,2] [,3] [,4] # [1,] 1 6 11 16 # [2,] 3 8 13 18 # [3,] 23 28 33 38 # [4,] 24 29 34 39 # [5,] 5 10 15 20 # [6,] 21 26 31 36 # [7,] 22 27 32 37 # [8,] 2 7 12 17 # [9,] 4 9 14 19 # [10,] 25 30 35 40 # attr(,"origdim") # [1] 5 4 2 ind1,主要是为了查看内部发生了什么。您可以将ind2替换为m[ind2,]以获得相同的效果。)

顺便说一句:如果我们使用了2的种子,我们会注意到2行没有被交换

m[sample(ind1),]

因此,我选择了3号种子进行示范。但是,这可能会使外观无法正常工作。由于缺乏更多控制代码,set.seed(2) (ind1 <- sample(nr, size = ceiling(nr * pct))) # [1] 2 7 5 10 6 (ind2 <- sample(ind1)) # [1] 6 2 5 10 7 无法确保位置发生变化:期望“随机交换行”可以随机选择将第2行移动到第2行当然是合理的。例如:

sample

第一个随机选择五行,然后将它们随机重新排序为不变的顺序。 (我建议如果你想强制它们都是动作,你应该问一个新问题,询问是否强迫set.seed(267) (ind1 <- sample(nr, size = ceiling(nr * pct))) # [1] 3 6 5 7 2 (ind2 <- sample(ind1)) # [1] 3 6 5 7 2 向量改变。

无论如何,我们可以使用第二个函数重新获得原始维度:

sample

在阵列的第一个平面中,第1行和第5行不变;在第二个平面中,第1,2和5行不变。五行相同,五行移动(但每行内没有变化)。