【问题标题】:Calculating distance between coordinates and reference point计算坐标和参考点之间的距离
【发布时间】:2022-01-08 06:41:10
【问题描述】:

我想计算 lat1、lon1 和参考点(52.92343、5.04127)之间的距离。我想对我的数据集中的每一行都这样做,所以距离将使用每一行中的参考来计算。这意味着我将创建一个以公里为单位的新列。我可以想象你将不得不使用某种循环函数,但到目前为止我还没有弄清楚如何完成这个。我想我将不得不使用包geodistgeosphere,但不幸的是没有成功。如何计算这些距离?

structure(list(Day = c("26", "05", "17", "18", "19", "19"), Month = c("07", 
"08", "08", "08", "08", "08"), Year = c("2021", "2021", "2021", 
"2021", "2021", "2021"), Location.Receiver = c("Den Oever Ijsselmeer", 
"Medemblik Ijsselmeer, gemaal", "Den Oever Ijsselmeer", "Den Oever Ijsselmeer", 
"Den Oever Ijsselmeer", "Den Oever Ijsselmeer"), Transmitter = c("A69-1602-59776", 
"A69-1602-59777", "A69-1602-59776", "A69-1602-59776", "A69-1602-59769", 
"A69-1602-59776"), Batch.location = c("Den Oever", "Den Oever", 
"Den Oever", "Den Oever", "Den Oever", "Den Oever"), BatchNr = c(8, 
9, 8, 8, 1, 8), Latitude = c(52.92343, 52.76098, 52.92343, 52.92343, 
52.92343, 52.92343), Longitude = c(5.04127, 5.12172, 5.04127, 
5.04127, 5.04127, 5.04127), Date = structure(c(18834, 18844, 
18856, 18857, 18858, 18858), class = "Date")), row.names = c(1095729L, 
1180267L, 1072657L, 1092667L, 716601L, 1077415L), class = "data.frame")

【问题讨论】:

  • 您的dput() 输出不完整
  • 已修复,谢谢!

标签: r coordinates distance


【解决方案1】:

无需循环,您可以使用geodist 计算x 中的坐标数组中的条目与y 中的单个点之间的距离。只需将坐标作为 lon/lat 显式传递并作为数字向量保存回Distance,而不是作为原始矩阵输出。

library(geodist)

df$Distance <- as.numeric(geodist(df[,9:8], c(5.04127, 52.92343)))
#> object has no named columns; assuming order is lon then lat

df$Distance
#> [1]     0.00 18843.92     0.00     0.00     0.00     0.00

【讨论】:

    【解决方案2】:

    请使用 sfunits 库找到替代解决方案(参见下面的代表)

    Reprex

    • 代码
    library(sf)
    library(units)
    
    # Convert the df into 'sf' object
    df_sf <- df %>% 
      st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326)
    
    # Create the reference 'sf' object
    ref_point_sf <- st_point(c(5.04127, 52.92343)) %>% 
      st_coordinates() %>% 
      as.data.frame() %>% 
      st_as_sf(coords = c("X", "Y"), crs = 4326)
    
    # Compute the distance between the reference point and points from 'df_sf'
    results <- st_distance(ref_point_sf, df_sf) %>% 
      set_units("km")
    
    • 输出
    results
    #> Units: [km]
    #>      [,1]     [,2] [,3] [,4] [,5] [,6]
    #> [1,]    0 18.85446    0    0    0    0
    

    reprex package (v2.0.1) 于 2021-12-01 创建


    作为您评论的后续行动

    • 代码
    library(sf)
    library(units)
    library(dplyr)
    
    
    # Convert df into 'sf' object
    df_sf <- df %>% 
      st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326)
    
    # Create the reference 'sf' object
    ref_point_sf <- st_point(c(5.04127, 52.92343)) %>% 
      st_coordinates() %>% as.data.frame() %>% 
      st_as_sf(coords = c("X", "Y"), crs = 4326)
    
    # Compute the distance between the reference point and points from 'df_sf'
    results <- st_distance(df_sf, ref_point_sf) %>% 
      set_units("km") %>% 
      as.data.frame() %>% 
      drop_units() %>% 
      `colnames<-`(., "dist_km")
    
    # Add 'results' in the original dataframe
    df <- df %>% 
      mutate(dist_km = results)
    
    • 输出
    df
    #>         Day Month Year            Location.Receiver    Transmitter
    #> 1095729  26    07 2021         Den Oever Ijsselmeer A69-1602-59776
    #> 1180267  05    08 2021 Medemblik Ijsselmeer, gemaal A69-1602-59777
    #> 1072657  17    08 2021         Den Oever Ijsselmeer A69-1602-59776
    #> 1092667  18    08 2021         Den Oever Ijsselmeer A69-1602-59776
    #> 716601   19    08 2021         Den Oever Ijsselmeer A69-1602-59769
    #> 1077415  19    08 2021         Den Oever Ijsselmeer A69-1602-59776
    #>         Batch.location BatchNr Latitude Longitude       Date  dist_km
    #> 1095729      Den Oever       8 52.92343   5.04127 2021-07-26  0.00000
    #> 1180267      Den Oever       9 52.76098   5.12172 2021-08-05 18.85446
    #> 1072657      Den Oever       8 52.92343   5.04127 2021-08-17  0.00000
    #> 1092667      Den Oever       8 52.92343   5.04127 2021-08-18  0.00000
    #> 716601       Den Oever       1 52.92343   5.04127 2021-08-19  0.00000
    #> 1077415      Den Oever       8 52.92343   5.04127 2021-08-19  0.00000
    

    reprex package (v2.0.1) 于 2021-12-02 创建

    【讨论】:

    • 我已将您的代码应用到我的脚本中,它似乎可以工作。但是,正如我正确理解的那样,results 的值现在是 1 行,有 2525 个单位。我想要在我的原始数据集中添加一个额外的列,其中包含您在results 中输入的计算距离。最好的方法是什么?
    • 嗨@Pepijn Vermeiren,请在我的编辑上方找到您的评论。希望这就是你要找的。干杯。
    • 绝对惊人,正是我想要的。谢谢!
    • 非常感谢您的反馈@Pepijn95。很高兴我能帮助你。请考虑将此答案标记为“已接受”,以便其他 SO 用户更容易找到正确答案。我祝你工作顺利。干杯。
    【解决方案3】:

    points_in_circle() 从参考点返回给定radius 内的点。以下返回参考点1000km内的所有点:

    
    library(spatialrisk)
    points_in_circle(df, lat_center = 52.92343, lon_center = 5.04127, 
                     lon = Longitude, lat = Latitude, radius = 1e6)
    #>         Day Month Year            Location.Receiver    Transmitter
    #> 1095729  26    07 2021         Den Oever Ijsselmeer A69-1602-59776
    #> 1072657  17    08 2021         Den Oever Ijsselmeer A69-1602-59776
    #> 1092667  18    08 2021         Den Oever Ijsselmeer A69-1602-59776
    #> 716601   19    08 2021         Den Oever Ijsselmeer A69-1602-59769
    #> 1077415  19    08 2021         Den Oever Ijsselmeer A69-1602-59776
    #> 1180267  05    08 2021 Medemblik Ijsselmeer, gemaal A69-1602-59777
    #>         Batch.location BatchNr Latitude Longitude       Date distance_m
    #> 1095729      Den Oever       8 52.92343   5.04127 2021-07-26       0.00
    #> 1072657      Den Oever       8 52.92343   5.04127 2021-08-17       0.00
    #> 1092667      Den Oever       8 52.92343   5.04127 2021-08-18       0.00
    #> 716601       Den Oever       1 52.92343   5.04127 2021-08-19       0.00
    #> 1077415      Den Oever       8 52.92343   5.04127 2021-08-19       0.00
    #> 1180267      Den Oever       9 52.76098   5.12172 2021-08-05   18875.55
    

    reprex package (v2.0.1) 于 2021-12-02 创建

    【讨论】:

    • 太棒了!这对我有用。感谢您的帮助!