shuffle/permutate 逐块向量
shuffle/permutate vector block-wise
我正在尝试打乱一个简单向量的元素,但我想按块执行此操作,因此简单的 sample
操作不起作用。
我的意思是,每 2 个连续值属于一个“块”,我只想打乱这些块,即不打乱各个值。
虽然我想使用 group_by
将我的值组合在一起,但每个块中的值除了一起出现外没有任何共同点。
这是示例向量的样子。 (实向量有超过 5e6 个元素)。
<------- BLOCK1 -----> <----- BLOCK 2 ------> ........
x <- c(0.15055060, 0.69097695, 0.89731929, 0.84515906, 0.54843043, 0.77026955, 0.05127419, 0.33850021, 0.47623089, 0.36896818)
“成功”的随机播放看起来像这样:
<------- BLOCK1 -----> <----- BLOCK 2 ------>
x <- c(0.05127419, 0.33850021, 0.15055060, 0.69097695, 0.47623089, 0.36896818, 0.89731929, 0.84515906, 0.54843043, 0.77026955)
非常感谢任何关于如何实现这一目标的见解!
只打乱块号 -
inds <- sample(length(x)/2) * 2
x[c(rbind(inds - 1, inds))]
length(x)/2
是x
中的块数
- 我们
sample
他们乘以2得到每个块的第二个值
- 从中减-1得到第一个块值
- 将它们组合在一起并将其用作
x
. 的子集的索引
任何大小的块的一般解决方案是 -
n <- 5000 #block size
inds <- sample(length(x)/n) * n
x[c(sapply(inds, `-`, (n-1):0))]
由于矩阵在 R
中按列存储,我们可以简单地将向量转换为行数等于块大小的矩阵。之后,我们需要做的就是打乱矩阵的列并将其转换回向量。这是一个简单的函数:
ShuffleBlocks <- function(v, size = 2L) {
size <- as.integer(size)
stopifnot(length(v) %% size == 0L)
mat <- matrix(v, nrow = size)
as.vector(mat[, sample(ncol(mat))])
}
在 OP 的示例中调用它:
set.seed(42)
ShuffleBlocks(x)
# [1] 0.15055060 0.69097695 0.47623089 0.36896818 0.05127419 0.33850021 0.54843043 0.77026955 0.89731929 0.84515906
# x[1] x[2] x[9] x[10] x[7] x[8] x[5] x[6] x[3] x[4]
x
#[1] 0.15055060 0.69097695 0.89731929 0.84515906 0.54843043 0.77026955 0.05127419 0.33850021 0.47623089 0.36896818
对于不同的块大小,这可以顺利推广。例如:
set.seed(321)
ShuffleBlocks(x, size = 5)
# [1] 0.77026955 0.05127419 0.33850021 0.47623089 0.36896818 0.15055060 0.69097695 0.89731929 0.84515906 0.54843043
我正在尝试打乱一个简单向量的元素,但我想按块执行此操作,因此简单的 sample
操作不起作用。
我的意思是,每 2 个连续值属于一个“块”,我只想打乱这些块,即不打乱各个值。
虽然我想使用 group_by
将我的值组合在一起,但每个块中的值除了一起出现外没有任何共同点。
这是示例向量的样子。 (实向量有超过 5e6 个元素)。
<------- BLOCK1 -----> <----- BLOCK 2 ------> ........
x <- c(0.15055060, 0.69097695, 0.89731929, 0.84515906, 0.54843043, 0.77026955, 0.05127419, 0.33850021, 0.47623089, 0.36896818)
“成功”的随机播放看起来像这样:
<------- BLOCK1 -----> <----- BLOCK 2 ------>
x <- c(0.05127419, 0.33850021, 0.15055060, 0.69097695, 0.47623089, 0.36896818, 0.89731929, 0.84515906, 0.54843043, 0.77026955)
非常感谢任何关于如何实现这一目标的见解!
只打乱块号 -
inds <- sample(length(x)/2) * 2
x[c(rbind(inds - 1, inds))]
length(x)/2
是x
中的块数
- 我们
sample
他们乘以2得到每个块的第二个值 - 从中减-1得到第一个块值
- 将它们组合在一起并将其用作
x
. 的子集的索引
任何大小的块的一般解决方案是 -
n <- 5000 #block size
inds <- sample(length(x)/n) * n
x[c(sapply(inds, `-`, (n-1):0))]
由于矩阵在 R
中按列存储,我们可以简单地将向量转换为行数等于块大小的矩阵。之后,我们需要做的就是打乱矩阵的列并将其转换回向量。这是一个简单的函数:
ShuffleBlocks <- function(v, size = 2L) {
size <- as.integer(size)
stopifnot(length(v) %% size == 0L)
mat <- matrix(v, nrow = size)
as.vector(mat[, sample(ncol(mat))])
}
在 OP 的示例中调用它:
set.seed(42)
ShuffleBlocks(x)
# [1] 0.15055060 0.69097695 0.47623089 0.36896818 0.05127419 0.33850021 0.54843043 0.77026955 0.89731929 0.84515906
# x[1] x[2] x[9] x[10] x[7] x[8] x[5] x[6] x[3] x[4]
x
#[1] 0.15055060 0.69097695 0.89731929 0.84515906 0.54843043 0.77026955 0.05127419 0.33850021 0.47623089 0.36896818
对于不同的块大小,这可以顺利推广。例如:
set.seed(321)
ShuffleBlocks(x, size = 5)
# [1] 0.77026955 0.05127419 0.33850021 0.47623089 0.36896818 0.15055060 0.69097695 0.89731929 0.84515906 0.54843043