如何进行无重复且无连续相同值的抽样。

10

我已经花了一天多的时间去完成看起来非常简单的事情。我需要创建300个“随机”序列,其中数字1、2、3和4都恰好出现12次,但是同一个数字不能在连续的位置上使用两次。

我最好的尝试(我猜)是:

  1. 让R从48个项目中无重复地随机抽取样本,测试其中是否存在连续值,然后仅使用不包含连续值的序列。 问题:几乎没有满足此标准的随机序列,因此这需要很长时间。

  2. 让R创建不包含连续值的序列(见代码)。

pop<-rep(1:4,12)
y=c()
while(length(y)!=48)
  {
  y= c(y,sample(pop,48-length(y),replace=F))
  y=y[!c(FALSE, diff(y) == 0)]
  }
问题:这会创建包含各种数量值的序列。我尝试仅使用恰好包含12个值的序列,但这只是让我回到了问题1:需要很长时间才能完成。
一定有某种简单的方法可以做到这一点,对吧?非常感谢您的帮助!
3个回答

3

也许使用 replicate() 和一个 repeat 循环会更快。下面是一个包含3个序列的示例。看起来,对于300(未经测试),这将需要大约1490秒。

set.seed(42)
seqc <- rep(1:4, each=12)  # starting sequence

system.time(
  res <- replicate(3, {
    repeat {
      seqcs <- sample(seqc, 48, replace=FALSE) 
      if (!any(diff(seqcs) == 0)) break
    }
    seqcs
  })
)
#  user  system elapsed 
# 14.88    0.00   14.90 

res[1:10, ]
#       [,1] [,2] [,3]
#  [1,]    4    2    3
#  [2,]    1    1    4
#  [3,]    3    2    1
#  [4,]    1    1    4
#  [5,]    2    3    1
#  [6,]    4    1    2
#  [7,]    3    4    4
#  [8,]    2    1    1
#  [9,]    3    4    4
# [10,]    4    3    2

1
非常感谢!创建100个序列花费了800秒,这在这种情况下完全可以接受。解决了我的问题! - CookieMons

1
你可以取出连续的值并将它们放在不连续的位置。
unConsecutive  <- function(x) {
    repeat{
        tt <- c(FALSE, diff(x)==0)
        if(any(tt)) {
            y <- x[which(tt)]
            x <- x[which(!tt)]
            i <- x != y[1]
            i  <- which(c(c(TRUE, diff(i)==0) & i,FALSE)
                        | c(FALSE, c(diff(i)==0, TRUE) & i))
            if(length(i) > 0) {
                i <- i[1]-1
                x <- c(x[seq_len(i)], y, x[i+seq_len(length(x)-i)])
            } else {
                x  <- c(x, y)
                break
            }
        } else {break}
    }
    x
}

unConsecutive(c(1,1,2))
#[1] 1 2 1
unConsecutive(c(1,1,1))
#[1] 1 1 1

set.seed(7)
system.time(
    res <- replicate(300, unConsecutive(sample(rep(1:4,12))))
)
#   user  system elapsed 
#  0.058   0.011   0.069 
all(apply(res, 2, table) == 12)
#[1] TRUE
all(apply(res, 2, diff) != 0)
#[1] TRUE

1
另一种选择是使用马尔科夫链蒙特卡罗方法随机交换2个数字,并仅在满足以下条件时移动到新样本:1)我们没有交换相同的数字,2)没有2个相同的数字相邻。为了解决相关样本问题,我们可以生成大量样本,然后随机选择其中的300个。
v <- rep(1:4, 12)
l <- 48
nr <- 3e5
m <- matrix(0, nrow=nr, ncol=l)
count <- 0
while(count < nr) {
    i <- sample(l, 2)
    if (i[1L] != i[2L]) {
        v[i] = v[i[2:1]]
        if (!any(diff(v)==0)) {
            count <- count + 1
            m[count, ] <- v
        } else {
            v[i] = v[i[2:1]]
        }
    }
}
a <- m[sample(nr, 300),]
a

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接