在子数组之间移动行 [英] Moving rows between subarrays

查看:44
本文介绍了在子数组之间移动行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a number of subarrays, say 2 (for simplicity), each with the same number of rows and columns. Each spot in the subarrays is occupied by a number in [1, 10].

我想做的是根据移动速率 m = [0, 1] 在子阵列之间随机移动行.m = 0 对应不移动,而 m = 1 表示所有子阵列中的任何行都可以移动.

What I would like to do is move rows randomly between subarrays according to some rate of movement m = [0, 1]. m = 0 corresponds to no movement, while m = 1 means that any rows across all subarrays can be moved.

我的灵感来自:

如何交换R中两行之间的一些值

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

but my problem is a bit different than this. I do know that sample() would be needed here.

是否有一种简单的方法可以实现这一目标?

Is there an easy way to go about accomplishing this?

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

This doesn't do it, but I believe I'm on the right track anyway.

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),那会容易得多.

It is significantly easier if you can use 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

(我将再次将种子设置为方便让我展示一些有趣"的东西.)

(I'm going to set the seed again to something that conveniently gives me something "interesting" to show.)

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

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

The first randomness, runif, is compared against m and generates the indices that may change. The second randomness, sample below, takes those indices and possibly reorders them. (In this case, it reorders "1,4,7" to "4,1,7", meaning the third of the rows-that-may-change will be left unchanged.)

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%(甚至任何)的行将被交换.

Note that this is probabilistic, which means a probability of 0.2 does not guarantee you 20% (or even any) of the rows will be swapped.

(因为我猜你真的想保留你的 3-dim(甚至 n-dim)array,你也许可以使用 aperm数组<-->矩阵之间传输.)

(Since I'm guessing you'd really like to preserve your 3-dim (or even n-dim) array, you might be able to use aperm to transfer between array <--> matrix.)

编辑 1

作为 runif 的概率使用的替代方法,您可以使用:

As an alternative to a probabilitic use of runif, you can use:

ind <- head(sample(d[1]),size=d[1]*m) 

更接近20%"的目标.由于 d[1]*m 通常不是整数,head 会默默地将数字截断/取舍,因此您将获得价格合适的赢家:最接近达到但不超过您想要的百分比.

to get closer to your goal of "20%". Since d[1]*m will often not be an integer, head silently truncates/floors the number, so you'll get the price-is-right winner: closest to but not over your desired percentage.

编辑 2

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

A reversible method for transforming an n-dimensional array into a matrix and back again. Caveat: though the logic appears solid, my testing has only included a couple arrays.

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" 属性(如果仍然存在);只要您对矩阵的修改没有清除其属性,这就会起作用.(简单的行交换不会.)

The reversal uses the "origdim" attribute if still present; this will work as long as your modifications to the matrix do not clear its attributes. (Simple row-swapping does not.)

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).)

(These two functions should probably do some more error-checks, such as 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

EDIT 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%.

The random-swapping of rows. I'm using 50% here.

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

(注意,我在这里预先制作了 ind1ind2,主要是为了看看内部发生了什么.你可以替换 m[ind2,]m[sample(ind1),] 相同的效果.)

(Note that I pre-made ind1 and ind2 here, mostly to see what was going on internally. You can replace m[ind2,] with m[sample(ind1),] for the same effect.)

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

BTW: if we had instead used a seed of 2, we would notice that 2 rows are not swapped:

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 并不能确保位置改变:期望随机交换行"可以随机选择将第 2 行移动到第 2 行当然是合理的.例如:

Because of this, I chose a seed of 3 for demonstration. However, this may give the appearance of things not working. Lacking more controlling code, sample does not ensure that positions change: it is certainly reasonable to expect that "randomly swap rows" could randomly choose to move row 2 to row 2. Take for example:

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向量改变.em>)

The first randomly chooses five rows, and then reorders them randomly into an unchanged order. (I suggest that if you want to force that they are all movements, you should ask a new question asking about just forcing a sample vector to change.)

无论如何,我们可以通过第二个函数恢复原始维度:

Anyway, we can regain the original dimensionality with the second function:

(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 行保持不变.五行相同,五行移动(但每行内其他方面不变).

In the first plane of the array, rows 1 and 5 are unchanged; in the second plane, rows 1, 2, and 5 are unchanged. Five rows the same, five rows moved around (but otherwise unchanged within each row).

这篇关于在子数组之间移动行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆