在子数组之间移动行
Moving rows between subarrays
我有许多子数组,比如 2 个(为简单起见),每个子数组的行数和列数相同。子数组中的每个点都被 [1, 10] 中的一个数字占据。
我想做的是根据某个移动速率 m = [0, 1] 在子数组之间随机移动行。 m = 0 对应于没有移动,而 m = 1 意味着可以移动所有子数组中的任何行。
我的灵感来自:
但我的问题与此略有不同。我知道这里需要 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.
如有任何帮助,我们将不胜感激。
如果你可以使用 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
(我将再次设置种子,以便方便地给我一些 "interesting" 来展示。)
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%(甚至 any)将交换行。
(因为我猜你真的很想保留你的 3-dim(甚至 n-dim)array
,你也许可以使用 aperm
在 array <--> matrix
之间转移。)
编辑 1
作为概率使用 runif
的替代方法,您可以使用:
ind <- head(sample(d[1]),size=d[1]*m)
更接近“20%”的目标。由于 d[1]*m
通常不是整数,head
默默地 truncates/floors 数字,因此您将获得价格合适的赢家:最接近但不超过您想要的百分比。
编辑 2
一种可逆的方法,用于将 n 维数组转换为矩阵并再次转换回来。 警告:虽然逻辑看起来很可靠,但我的测试只包含几个数组。
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
可逆性证明:
identical(matrix2array(m), a)
# [1] TRUE
编辑 3,"WRAP UP of all code"
创建虚假数据:
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
行的随机交换。我这里用了 50%。
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,]
替换为 m[sample(ind1),]
同样的效果。)
顺便说一句:如果我们改为使用 2 的种子,我们会注意到 2 行 没有交换:
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
正因如此,我选择了3个种子进行演示。但是,这可能会使事情看起来不起作用。缺少更多控制代码,sample
不能确保位置发生变化:期望 "randomly swap rows" 可以随机选择将第 2 行移动到第 2 行当然是合理的。举个例子:
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
向量改变。 )
无论如何,我们可以通过第二个函数恢复原来的维度:
(a2 <- matrix2array(m))
# , , 1
# [,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
# , , 2
# [,1] [,2] [,3] [,4]
# [1,] 21 26 31 36
# [2,] 22 27 32 37
# [3,] 2 7 12 17
# [4,] 4 9 14 19
# [5,] 25 30 35 40
阵列的第一个平面,第1行和第5行不变;在第二个平面中,第 1、2 和 5 行没有变化。五行相同,五行移动(但每行内其他方面不变)。
我有许多子数组,比如 2 个(为简单起见),每个子数组的行数和列数相同。子数组中的每个点都被 [1, 10] 中的一个数字占据。
我想做的是根据某个移动速率 m = [0, 1] 在子数组之间随机移动行。 m = 0 对应于没有移动,而 m = 1 意味着可以移动所有子数组中的任何行。
我的灵感来自:
但我的问题与此略有不同。我知道这里需要 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.
如有任何帮助,我们将不胜感激。
如果你可以使用 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
(我将再次设置种子,以便方便地给我一些 "interesting" 来展示。)
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%(甚至 any)将交换行。
(因为我猜你真的很想保留你的 3-dim(甚至 n-dim)array
,你也许可以使用 aperm
在 array <--> matrix
之间转移。)
编辑 1
作为概率使用 runif
的替代方法,您可以使用:
ind <- head(sample(d[1]),size=d[1]*m)
更接近“20%”的目标。由于 d[1]*m
通常不是整数,head
默默地 truncates/floors 数字,因此您将获得价格合适的赢家:最接近但不超过您想要的百分比。
编辑 2
一种可逆的方法,用于将 n 维数组转换为矩阵并再次转换回来。 警告:虽然逻辑看起来很可靠,但我的测试只包含几个数组。
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
可逆性证明:
identical(matrix2array(m), a)
# [1] TRUE
编辑 3,"WRAP UP of all code"
创建虚假数据:
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
行的随机交换。我这里用了 50%。
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,]
替换为 m[sample(ind1),]
同样的效果。)
顺便说一句:如果我们改为使用 2 的种子,我们会注意到 2 行 没有交换:
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
正因如此,我选择了3个种子进行演示。但是,这可能会使事情看起来不起作用。缺少更多控制代码,sample
不能确保位置发生变化:期望 "randomly swap rows" 可以随机选择将第 2 行移动到第 2 行当然是合理的。举个例子:
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
向量改变。 )
无论如何,我们可以通过第二个函数恢复原来的维度:
(a2 <- matrix2array(m))
# , , 1
# [,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
# , , 2
# [,1] [,2] [,3] [,4]
# [1,] 21 26 31 36
# [2,] 22 27 32 37
# [3,] 2 7 12 17
# [4,] 4 9 14 19
# [5,] 25 30 35 40
阵列的第一个平面,第1行和第5行不变;在第二个平面中,第 1、2 和 5 行没有变化。五行相同,五行移动(但每行内其他方面不变)。