R: làm thế nào để lấy mẫu mà không thay thế VÀ không có các giá trị liên tiếp giống nhau


10

Tôi đã dành hơn một ngày cố gắng để hoàn thành những gì dường như là một điều rất đơn giản. Tôi phải tạo ra 300 chuỗi 'ngẫu nhiên' trong đó các số 1,2,3 và 4 đều xuất hiện chính xác 12 lần, nhưng cùng một số không bao giờ được sử dụng hai lần 'liên tiếp' / liên tiếp.

Những nỗ lực tốt nhất của tôi (tôi đoán) là:

  1. có R mẫu 48 mục mà không thay thế, kiểm tra xem có giá trị liên tiếp với rle không, sau đó chỉ sử dụng các chuỗi không chứa giá trị liên tiếp. Vấn đề: hầu như không có chuỗi ngẫu nhiên nào đáp ứng tiêu chí này, vì vậy phải mất mãi mãi.

  2. có R tạo các chuỗi không có giá trị liên tiếp (xem mã).

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)]
  }

Vấn đề: điều này tạo ra các chuỗi với số lượng khác nhau của từng giá trị. Sau đó, tôi đã cố gắng chỉ sử dụng các chuỗi đó với chính xác 12 của mỗi giá trị, nhưng điều đó chỉ đưa tôi trở lại vấn đề 1: mất mãi mãi.

Phải có một số cách dễ dàng để làm điều này, phải không? Bất kỳ trợ giúp nào cũng được đánh giá rất cao!

Câu trả lời:


3

Có thể sử dụng replicate()với một repeatvòng lặp là nhanh hơn. đây là một ví dụ với 3trình tự. Có vẻ như điều này sẽ mất khoảng. 1490 giây với 300(không được kiểm tra).

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
Cảm ơn bạn rất nhiều! Tạo 100 chuỗi mất 800 giây, điều này hoàn toàn chấp nhận được trong trường hợp này. Giải quyết vấn đề của tôi!
CookieMons

1

Một tùy chọn khác là sử dụng phương pháp Markov Chain Monte-Carlo để hoán đổi ngẫu nhiên 2 số và chỉ chuyển sang mẫu mới khi 1) chúng ta không hoán đổi cùng một số và 2) không có 2 số giống nhau nào liền kề nhau. Để giải quyết các mẫu tương quan, chúng tôi có thể tạo ra rất nhiều mẫu và sau đó chọn ngẫu nhiên 300 mẫu:

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

1

Bạn có thể lấy ra các giá trị liên tiếp và đặt chúng ở nơi chúng không liên tiếp.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.