首页 > 解决方案 > 根据地理距离矩阵的结果更改列

问题描述

我有一个看起来像这样的数据框:

long       lat       site
-141.37    61.13     x1
-149.1833  66.7333   x2
-149.667   67.667    x3
-141.3667  61.1157   x4

我想计算所有site's using之间的距离distVincentyEllipsoid。然后对于那些彼此相距 5 公里以内的站点,我想修改site名称以包含两个站点。所以,在这个例子中x1x4彼此之间的距离在 5 公里以内,所以它会是这样的:

 long      lat       site  
-141.37    61.13     x1_x4    
-149.1833  66.7333   x2
-149.667   67.667    x3
-141.3667  61.1157   x1_x4

我知道我可以通过site这种方式计算 all 之间的矩阵:

df %>% dplyr::select('long', 'lat')
distm(df, fun = distVincentyEllipsoid)

但我不知道如何从那里拿走它。

标签: rgeosphere

解决方案


如果您将示例数据提供为 R 代码,这将很有帮助,如下所示

x <- matrix(c(-141.37, 61.13, -149.1833, 66.7333, -149.667, 67.667, -141.3667, 61.1157), ncol=2, byrow=TRUE)
colnames(x) <- c("lon", "lat")
x <- data.frame(site=paste0("x", 1:4), x)

但感谢您显示预期的输出

解决方案:

正如你所建议的,首先制作一个距离矩阵。然后将其分类为是否在阈值距离内,然后使用行来选择记录。请注意,我使用distGeo--- 这是比distVincentyEllipsoid.

library(geosphere)
m <- distm(x[, c("lon", "lat")], fun=distGeo)

m <- m < 5000
x$name <- apply(m, 1, function(i) paste(x$site[i], collapse="_"))
x
#  site       lon     lat    name
#1   x1 -141.3700 61.1300   x1_x4
#2   x2 -149.1833 66.7333      x2
#3   x3 -149.6670 67.6670      x3
#4   x4 -141.3667 61.1157   x1_x4

如果你有很多点,距离矩阵可能会变得太大。在那种情况下,你可以做

y <- x[,  c("lon", "lat")]
for (i in 1:nrow(y)) {
   j <- distGeo(y[i, ], y) < 5000
   x$name[i] <- paste(x$site[j], collapse="_")
} 

或者像这样

y <- x[,  c("lon", "lat")]
x$name <- x$site    
for (i in 1:nrow(y)) {
   j <- distGeo(y[i, ], y) < 5000
   if (any(j)) {
       x$name[i] <- paste(x$site[j], collapse="_")
   }
} 

推荐阅读