[英]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.