我有许多子数组,比如说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.
感谢任何帮助。
答案 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
将第一个随机性runif
与m
进行比较,并生成可能更改的索引。下面的第二个随机性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行不变。五行相同,五行移动(但每行内没有变化)。