簡體   English   中英

如何將間隔隨機分為相等長度的非重疊,間隔的箱

[英]How to randomly divide interval into non overlapping, spaced bins of equal length

我有一個從1到671的間隔。我想將其划分為5個長度為50的隨機非重疊bin,但間隔為min 51。

interval <- 1:671  (example, it does not need to be 671)

結果(這是一個示例,因為垃圾箱應該是隨機的,但應在間隔內,等長且按照定義的間距排列):

bin1 <- 3:52
bin2 <- 103:152
bin3 <- 209:258
bin4 <- 425:474
bin5 <- 610:659

我希望輸出為dataframe(bin,startOfbin,endOfbin),但其他類型(如list)也可以。

我目前正在用R編寫一個函數,該函數將在大量間隔內使用此采樣,並且我無法提出明智的解決方案。 先感謝您。

如果我正確理解了您的問題,則需要間隔的5個部分,長度為50,最小距離為51。

因此,您的隨機性在於每個距離比51大得多。

這意味着您需要計算實際分配多少空間。

intervalLength <- 671
nBins <- 5
binWidth <- 50
binMinDistance <- 51

spaceToDistribute <- intervalLength - (nBins * binWidth + (nBins - 1) * binMinDistance)

計算此值的隨機分割

distances <- diff(floor(c(0, sort(runif(nBins))) * spaceToDistribute))

並構造您所需的data.frame

startOfBin <- cumsum(distances) + (0:(nBins-1)) * 101
result <- data.frame(bin = 1:nBins, startOfBin = startOfBin, endOfBin = startOfBin + 49)

我不知道這是否具有所需的隨機性:

interval <- 1:671 

set.seed(42)

repeat { #rejection sampling
  int <- list(interval)
  s <- integer(5) * NA

  for (i in 1:5) {
    #sample an interval from the list
    sel <- sample(length(int), 1)
    isel <- int[[sel]]

    #sample start value
    s[[i]] <- sample(head(isel,-49), 1)

    #remove sampled values from interval
    sp <-
      split(isel, findInterval(isel, c(0, s[[i]], s[[i]] + 50, Inf)))
    if (s[[i]] > isel[1] &&
        s[[i]] < length(isel) - 49)
      sp <- sp[-2]
    else
      if (s[[i]] == isel[1])
        sp <- sp[-1]
    else
      if (s[[i]] == length(isel) - 49)
        sp <- head(sp,-1)
    sp <- sp[lengths(sp) >= 50]
    int <- c(sp, int[-sel])

    #break out of for loop 
    #if not enough intervals of sufficient length left
    if (length(int) < 1) break
  }
  if (!anyNA(s)) break
}

s
#[1] 321  74 245 170 441

library(ggplot2)
ggplot(data.frame(s = s, e = s + 49), aes(x = s, xend = e, y = 0, yend = 0)) +
  geom_segment(size = 3) +
  theme_minimal() +
  theme(axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        panel.grid.major.y = element_blank()) +
  xlab("") + ylab("")

結果圖

這樣的事情可能會起作用:

set.seed(111)

n_bins <- 5
bl <- 50
spacing <- 51

start <- 1
end <- 671


end_int <- end - n_bins*bl - (n_bins-1)*spacing
first_bin_start <- sample(start:end_int, 1)
first_bin_end <- first_bin_start + bl
avail_spacing <- end - first_bin_end - (n_bins-1)*bl - (n_bins-1)*spacing

sp <- c()
for (i in 1:(n_bins-1)){
  end <- sample(1:avail_spacing, 1)
  sp <- c(sp, end)
  avail_spacing <- avail_spacing - end
}


bin_start <- c(first_bin_start, first_bin_start + cumsum(spacing + bl + sp))
bin_end <- bin_start + bl

df <- data.frame(bin = 1:n_bins,
                 bin_start = bin_start,
                 bin_end = bin_end)

df

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM