【问题标题】:Minimum distance between two sets of co-ordinates两组坐标之间的最小距离
【发布时间】:2018-07-09 19:56:56
【问题描述】:

我有两个不同大小的包含地理编码的数据框。第一个(df)有 12,000 个观察值,第二个(学校)有 3,000 个。

第一个包含一个国家/地区的房产的地理编码,第二个包含该国家/地区的学校的地理编码。

我想找到每处房产最近学校的距离。使用 geosphere 包我目前正在使用以下内容:

library(geosphere)
for(i in 1:length(df$longitude)){
  df$dist2[i] <- distm(c(schools[1, 3], schools[1, 2]), c(df$longitude[i], df$latitude[i]), fun = distHaversine)  *0.001
}

其中schools[, 3]schools[, 2] 分别是该数据框的经度和纬度列。

上面计算了df 中的所有观测值与schools 中的第一所学校之间的距离(以公里为单位)。

我想计算每个观测值与所有 schools 之间的距离,只保存最小距离作为df$dist2[i] 的值。

【问题讨论】:

    标签: r geocoding


    【解决方案1】:

    在下面的例子中,我将点和学校的经纬度数据组成。

    library(tidyverse)
    library(geosphere)
    
    df_points  <- data.frame(lon = rnorm(10, mean =4, sd = 0.5), lat = rnorm(10, mean = 50, sd= 0.1))
    df_schools <- data.frame(lon = rnorm( 3, mean =4, sd = 0.5), lat = rnorm( 3, mean = 50, sd= 0.1))
    
    distm(df_points, df_schools, fun = distHaversine ) %>% 
      as.data.frame() %>% 
      rownames_to_column(var = "point_id") %>% 
      mutate(point_id = as.numeric(point_id)) %>%
      gather(key = school, value = distance, -point_id) %>%
      group_by(point_id) %>% 
      summarise(smalles_distance = min(distance))
    

    【讨论】:

      【解决方案2】:

      这是一种使用 sp 类对象的方法。您可以使用以下方式将 data.frame 对象强制转换为 SpatialPointsDataFrame 对象:coordinates(x) &lt;- ~lon+lat 这里的想法是派生两个点要素类之间的距离矩阵,然后根据列名提取距离和 ID(分配自学校数据)。这不仅会返回距离,而且还会返回每所学校的唯一标识符,从而可以轻松查询与任何给定属性特征最近的实际学校。

      首先,添加所需的库并创建一些示例数据。

      library(sp)
      library(raster)
      
      e <- as(raster::extent(-180, 180, -90, 90), "SpatialPolygons")
        properties <- spsample(e, 1000, type="random")
          proj4string(properties) <- "+proj=longlat +ellps=WGS84"  
        schools <- spsample(e, 100, type="random")
          proj4string(schools) <- "+proj=longlat +ellps=WGS84"
            schools$ids <- paste0("school", 1:length(schools))   
      

      现在,我们可以创建距离矩阵,将对角线分配给 NA,并将学校的唯一标识符添加到矩阵的列名。

      d <- spDists(x = properties, y = schools, longlat = TRUE)
        diag(d) <- NA
          colnames(d) <- schools$ids
      

      当然有更优雅的方法可以做到这一点,但为了简单起见,我们将使用一个 for 循环来填充代表距离和 ID 的两个向量。我们使用which.min 将索引拉到第 i 行的最小距离。迭代器基于矩阵行,因为它们代表属性特征。

      sdist <- rep(NA, nrow(d))
      sid <- rep(NA, nrow(d))
        for(i in 1:nrow(d)) {
          srow <- d[i,]  
          sdist[i] <- srow[which.min(srow)]
          sid[i] <- names(srow)[which.min(srow)]
        }
      

      然后我们可以将结果向量分配给属性 SpatialPointsDataFrame。现在我们在 @data 槽 data.frame 中有列,表示到最近学校的距离以及学校 ID。

      properties$school <- sid
      properties$dist <- sdist
      

      在这里我们可以绘制结果。

      par(mfrow=c(2,1))  
        plot(properties, pch=19, cex=0.5)
          plot(schools, pch=19, col="red", add=TRUE)
            plot(e, add=TRUE)
              title("random properties (black) and schools (red)", cex=0.5) 
        plot(properties, col="white")
          plot(properties[1,], pch=19, cex=2, add=TRUE)
            plot(schools[which(schools$ids %in% properties[1,]$school),], 
               pch=19, cex=2, col="red", add=TRUE)
                 plot(e, add=TRUE)
                 title("Property 1 (black) and closest school (red)", cex=0.5)
           sidx <- which(schools$ids %in% properties[1,]$school)
             text(coordinates(schools[sidx,]), 
                  label = schools[sidx,]$ids, col="blue", cex=1)
      

      【讨论】:

        猜你喜欢
        • 2021-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-06
        相关资源
        最近更新 更多