根据距离制作 'fake' 组 lat/long 坐标

Make a 'fake' set of lat/long coordinates based on distances

我希望根据彼此之间的距离(以公里或米为单位)构建一个 'fake' 坐标矩阵(即,它们可以在地球上的任何地方)。

我有一个包含位置之间距离的数据框。

dist_df<- data.frame(site1=c("a","b","c","d"),
                     site2=c("b","c","d","a"),
                     distance = c(222.1, 672.4, 45.2, 65.4))

但实际坐标之间存在障碍。因此,我用 another bit of code 绕过了障碍物以获得最小成本距离。为了运行一系列后面的功能我需要lat/long。我认为最简单的方法是根据相对最小成本距离生成 'fake' 坐标。

我希望获得类似以下的东西:

coordinates_sites<-data.frame(site=c("a","b","c","d"), 
                              lat=c(34.5332,32.1232,30.4232,30.4232),
                              long=c(-120.2222,-125.4422,-123.3512,-122.4232))

对执行此操作的最佳方法有什么想法吗?非常感谢!

这是一个使用 cmdscale 的解决方案。由于 cmdscale 需要一个完整的距离矩阵,我不得不在您提供的数据框中填写缺失的距离:

dist_df<- data.frame(site1=c("a","b","c","d", "d", "c"),
                     site2=c("b","c","d","a", "b", "a"),
                     distance = c(222.1, 672.4, 45.2, 65.4, 10.3, 110.1))

dst <- dist_df  %>%
  {
    names <- union(.$site1, .$site2)
    m <- matrix(0,
                nrow = length(names),
                ncol = length(names),
                dimnames = list(names, names))
    m[cbind(.$site1, .$site2)] <- pull(., distance)
    m[cbind(.$site2, .$site1)] <- pull(., distance)
    diag(m) <- 0
    as.dist(m)
  } 

dst

##>       a     b     c
##> b 222.1            
##> c 110.1 672.4      
##> d  65.4  10.3  45.2

fake坐标可以通过以下方式获取:

cmdscale(dst)

##>        [,1]        [,2]
##>a  -19.88532  39.4181776
##>b  341.11969  -0.9109572
##>c -331.30946  -4.3427637
##>d   10.07509 -34.1644567

请注意,cmdscale 返回的解决方案是一种优化,不会忠实地保留输入距离:

dist(cmdscale(dst))

##>           a         b         c
##> b 363.25068                    
##> c 314.48372 672.43790          
##> d  79.44829 332.71057 342.68461

但是,如果您从实际距离矩阵开始,cmdscale 可以准确地重建坐标。它显示在 cmdscale 示例中:

loc <- cmdscale(eurodist)
x <- loc[, 1]
y <- -loc[, 2] # reflect so North is at the top
## note asp = 1, to ensure Euclidean distances are represented correctly
plot(x, y, type = "n", xlab = "", ylab = "", asp = 1, axes = FALSE,
     main = "cmdscale(eurodist)")
text(x, y, rownames(loc), cex = 0.6)