以最小距离生成随机x和y坐标

时间:2018-02-07 12:07:22

标签: r coordinates spatial

R中是否有办法生成随机坐标,它们之间的距离最小?

E.g。我想避免的事情

x <- c(0,3.9,4.1,8)
y <- c(1,4.1,3.9,7)
plot(x~y)

5 个答案:

答案 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)

好的,这个怎么样?您只需生成无限制的随机数对,然后删除太近的onces。这可能是一个很好的开端:

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)

几乎立即运行并产生: enter image description here

答案 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])
)
相关问题