R中是否有办法生成随机坐标,它们之间的距离最小?
E.g。我想避免的事情
x <- c(0,3.9,4.1,8)
y <- c(1,4.1,3.9,7)
plot(x~y)
答案 0 :(得分:4)
这是随机几何的经典问题。空间中完全随机的点,落在不相交区域中的点数彼此独立,对应于均匀泊松点过程(在这种情况下,在R ^ 2中,但几乎可以在任何空间中)。
一个重要的特征是,在你可以使不相交区域中的点数独立之前,总点数必须是随机的。
对于泊松过程,点可以任意靠近。如果您通过对泊松过程进行采样来定义一个过程,直到您没有任何过于靠近的点,那么您就拥有了所谓的Gibbs Hardcore过程。这已在文献中进行了大量研究,并且有不同的方法来模拟它。 R包spatstat
具有执行此操作的功能。 rHardcore
是一个完美的采样器,但如果你想要一个高强度的点和一个很大的核心距离,它可能不会在有限的时间内终止......分布可以作为马尔可夫链的极限而得到{{{ 1}}允许您运行具有给定Gibbs模型的马尔可夫链作为其不变分布。这在有限的时间内完成,但只能实现近似分布。
在rmh.default
中,您还可以模拟固定数量的点数的条件。请注意,当您在有限的盒子中进行采样时,当然存在一个上限,即您可以使用给定的硬核半径适合多少个点,并且越接近此限制,从分布中正确采样就越成问题。
rmh.default
library(spatstat)
beta <- 100; R = 0.1
win <- square(1) # Unit square for simulation
X1 <- rHardcore(beta, R, W = win) # Exact sampling -- beware it may run forever for some par.!
plot(X1, main = paste("Exact sim. of hardcore model; beta =", beta, "and R =", R))
minnndist(X1) # Observed min. nearest neighbour dist.
#> [1] 0.102402
model <- rmhmodel(cif="hardcore", par = list(beta=beta, hc=R), w = win)
X2 <- rmh(model)
#> Checking arguments..determining simulation windows...Starting simulation.
#> Initial state...Ready to simulate. Generating proposal points...Running Metropolis-Hastings.
plot(X2, main = paste("Approx. sim. of hardcore model; beta =", beta, "and R =", R))
minnndist(X2) # Observed min. nearest neighbour dist.
#> [1] 0.1005433
X3 <- rmh(model, control = rmhcontrol(p=1), start = list(n.start = 42))
#> Checking arguments..determining simulation windows...Starting simulation.
#> Initial state...Ready to simulate. Generating proposal points...Running Metropolis-Hastings.
plot(X3, main = paste("Approx. sim. given n =", 42))
答案 1 :(得分:1)
您可以使用拒绝树苗https://en.wikipedia.org/wiki/Rejection_sampling
原理很简单:重新采样,直到数据验证条件为止。
> set.seed(1)
>
> x <- rnorm(2)
> y <- rnorm(2)
> (x[1]-x[2])^2+(y[1]-y[2])^2
[1] 6.565578
> while((x[1]-x[2])^2+(y[1]-y[2])^2 > 1) {
+ x <- rnorm(2)
+ y <- rnorm(2)
+ }
> (x[1]-x[2])^2+(y[1]-y[2])^2
[1] 0.9733252
>
答案 2 :(得分:1)
minimumDistancePairs <- function(x, y, minDistance){
i <- 1
repeat{
distance <- sqrt((x-x[i])^2 + (y-y[i])^2) < minDistance # pythagorean theorem
distance[i] <- FALSE # distance to oneself is always zero
if(any(distance)) { # if too close to any other point
x <- x[-i] # remove element from x
y <- y[-i] # and remove element from y
} else { # otherwise...
i = i + 1 # repeat the procedure with the next element
}
if (i > length(x)) break
}
data.frame(x,y)
}
minimumDistancePairs(
c(0,3.9,4.1,8)
, c(1,4.1,3.9,7)
, 1
)
将导致
x y
1 0.0 1.0
2 4.1 3.9
3 8.0 7.0
但请注意,这些不再是随机数(不过你解决了问题)。
答案 3 :(得分:1)
以下是一种天真的命中注意方法,对于某些参数选择(在问题中未指明),效果很好。如果性能成为问题,您可以尝试使用GPU加速距离矩阵计算的包gpuR。
rand.separated <- function(n,x0,x1,y0,y1,d,trials = 1000){
for(i in 1:trials){
nums <- cbind(runif(n,x0,x1),runif(n,y0,y1))
if(min(dist(nums)) >= d) return(nums)
}
return(NA) #no luck
}
这会在n
中重复绘制大小为[x0,x1]x[y0,y1]
的样本,然后如果不满足则将样本扔掉。作为一种安全措施,trials
可以防范无限循环。如果很难找到解决方案或n
很大,则可能需要增加或减少trials
。
例如:
> set.seed(2018)
> nums <- rand.separated(25,0,10,0,10,0.2)
> plot(nums)
答案 4 :(得分:-3)
我不确定你在问什么。
如果你想要随机坐标。
c(
runif(1,max=y[1],min=x[1]),
runif(1,max=y[2],min=x[2]),
runif(1,min=y[3],max=x[3]),
runif(1,min=y[4],max=x[4])
)