簡體   English   中英

geosphere / R:計算用4個點定義的兩個大圓之間的交點

[英]geosphere/R: Calculate intersection points between two great circles defined with 4 points

我正在嘗試使用geosphere來計算以數據幀格式給出的兩個大圓之間的交點,如下所示:

library(dplyr)
library(geosphere)

df <- data.frame(
  # first line
  ln1_lonb = 1:4,
  ln1_lone = 2:5,
  ln1_latb = 10:13,
  ln1_late = 11:14,
  # second line
  ln2_lonb = 5:8,
  ln2_lone = 6:9,
  ln2_latb = 14:17,
  ln2_late = 15:18
)

我嘗試使用gcintersect從功能geosphere即取矩陣作為輸入。 為了在數據幀中使用它,我使用了cbind ,但似乎mutate不適用於此:

df %>% 
  mutate(
    int_points = gcIntersect(
      cbind(ln1_lonb, ln1_latb),
      cbind(ln1_lone, ln1_late),
      cbind(ln2_lonb, ln2_latb),
      cbind(ln2_lone, ln2_late)
    )
  )
>Error: Column `int_points` must be length 4 (the number of rows) or one, not 16

可能錯誤是由於輸出比預期的更長(數據幀的行數)。 所以我試着把它放在一個列表中:

df %>% 
  mutate(
    int_points = list(gcIntersect(
      cbind(ln1_lonb, ln1_latb),
      cbind(ln1_lone, ln1_late),
      cbind(ln2_lonb, ln2_latb),
      cbind(ln2_lone, ln2_late)
    ))
  )

再次在這里,我看到輸出是所有組合,而不是獲得每行2個交叉點的4個坐標。

預期輸出將是新列中單元格中的列表,其中包含兩個點的坐標。

有沒有使用循環(或purrr )的解決方案,因為這將比mutate慢得多。

第一行中int_points的值應與此輸出的值相同:

gcIntersect(cbind(1,2), cbind(10,11), cbind(5,6), cbind(14,15))

我們可以做一個rowwise

library(tidyverse)
library(geosphere)
df %>% 
      rowwise %>% 
      mutate( int_points = list(gcIntersect(
        cbind(ln1_lonb, ln1_latb),
        cbind(ln1_lone, ln1_late),
        cbind(ln2_lonb, ln2_latb),
        cbind(ln2_lone, ln2_late)
     ))) %>% 
     ungroup %>%
    mutate(int_points = map(int_points, as_tibble)) %>% 
    unnest(int_points)
# A tibble: 4 x 12
#  ln1_lonb ln1_lone ln1_latb ln1_late ln2_lonb ln2_lone ln2_latb ln2_late  lon1  lat1  lon2  lat2
#     <int>    <int>    <int>    <int>    <int>    <int>    <int>    <int> <dbl> <dbl> <dbl> <dbl>
#1        1        2       10       11        5        6       14       15 -176. -12.6  3.61  12.6
#2        2        3       11       12        6        7       15       16 -175. -13.6  4.60  13.6
#3        3        4       12       13        7        8       16       17 -174. -14.6  5.60  14.6
#4        4        5       13       14        8        9       17       18 -173. -15.6  6.59  15.6

鑒於地圈方法是矢量化的(正如人們在R中所期望的那樣),我會這樣做

gcIntersect(df[,c(1,3)], df[,c(2,4)], df[,c(5,7)], df[,c(6,8)])

#          lon1      lat1     lon2     lat2
#[1,] -176.3902 -12.58846 3.609757 12.58846
#[2,] -175.3968 -13.58017 4.603188 13.58017
#[3,] -174.4023 -14.57291 5.597652 14.57291
#[4,] -173.4070 -15.56648 6.592953 15.56648

你也可以先這樣重組

d <- df[,c("ln1_lonb", "ln1_latb", "ln1_lone", "ln1_late", "ln2_lonb", "ln2_latb", "ln2_lone", "ln2_late")]

gcIntersect(d[,c(1,2)], d[,c(3,4)], d[,c(5,6)], d[,c(7:8)])

或者像這樣

begin1 <- df[,c("ln1_lonb", "ln1_latb")]
end1 <- df[,c("ln1_lone", "ln1_late")]
begin2 <- df[,c("ln2_lonb", "ln2_latb")]
end2 <- df[,c("ln2_lone", "ln2_late")]

gcIntersect(begin1, end1, begin2, end2)

我知道你特意要求使用mutate的解決方案,但我為其他需要清晰簡單解決方案的人添加了這些解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM