使用 R sf 估计多个国家和几何形状的点之间的距离及其相对海拔

问题描述 投票:0回答:1

我有多个国家/地区的多个点(经度、纬度)。这些点通过 ID 相关联,连接后会创建一条线。

 aus:
 id   country point_id      lon       lat
  1  Australia        0 130.1491 -19.57520
  1  Australia        1 129.9958 -19.48760
  1  Australia        2 129.7156 -19.25788
  1  Australia        3 129.7104 -19.20223
  2  Australia        0 129.2510 -18.59016
  2  Australia        1 129.5436 -18.30723
  3  Australia        0 137.2840 -20.06129
  3  Australia        1 137.2865 -20.04308
  3  Australia        2 137.1915 -20.00782
  3  Australia        3 137.1220 -19.97166
  3  Australia        4 137.0650 -19.91363
  3  Australia        5 136.8961 -19.85932
  4  Australia        0 136.8961 -19.85932
  4  Australia        1 136.8791 -19.88669
  4  Australia        2 136.8594 -19.91227
  4  Australia        3 136.8454 -19.92507
  4  Australia        4 136.8360 -19.92976

我在这篇文章之后成功创建了几何图形 [1],但是,我认为我的尝试可以进一步自动化。我尝试单独使用 group by ,如下所示:

# same logic as in [1] but by group
aus_group <- aus %>% group_by(id, country) 

b_group <- aus %>% group_by(id, country) %>% select(lon, lat)
e_group <- aus %>% group_by(id, country) %>% filter(row_number()!=1) %>% select(lon, lat)
f_group <- e_group %>% group_by(id, country) %>% summarise_all(last) %>% select(country, lon, lat)
g_group <- e_group %>% group_by(id, country) %>% rbind(f_group) %>% arrange(id)

aus_group$geometry = do.call(
  "c", 
  lapply(seq(nrow(b_group)), function(i) {
    st_sfc(
      st_linestring(
        as.matrix(
          rbind(b_group[i, c("lon", "lat")], g_group[i, c("lon", "lat")])
          )
        ),
      crs = 4326
      )
    }))

dat_g_sf = st_as_sf(aus_group)
mapview(dat_g_sf, zcol = "id")

# to compare with approach in [1]
dat_g_sf %>% filter(id==1) %>% mapview(zcol = "point_id") # got same plot
# so it works 

我分享这一部分,以防有改进 group_by 部分的建议

我的实际问题是关于点之间的距离估计以及这些点之间的相对海拔。

对于距离估计,我已经尝试过:

aus_2 <- aus_1 %>% select(id, country, point_id, lon, lat) #to avoid error with geometry
str(aus_2)
aus_2$distance = do.call(
  "c", 
  lapply(seq(nrow(b)), function(i) {
    st_distance(
      st_sfc(st_point
             (as.matrix(rbind(b[i, ], g[i, ]), by_element = TRUE)
               )
             ),
      crs = 4326
      )
    }))
Error in st_point(as.matrix(rbind(b[i, ], g[i, ]), by_element = TRUE)) : 
nrow(x) == 1 is not TRUE

我认为该错误可能与矩阵创建有关。我很感谢这里的任何帮助。

对于相对高程估计,我还没有找到以前使用 R 进行的工作。欢迎提出关于从哪里开始进行高程估计的建议。

另外,1中的“c”是什么意思?它在函数中是如何工作的?

r geospatial elevation
1个回答
0
投票

对于海拔,您需要一些数据源/提供者。

elevatr
包可能可以为您提供点位置的值,例如通过 Amazon Web Service Terrain Tiles,但您可能需要自己评估这些结果并计算出可接受的分辨率/缩放级别。

在这里,我假设“相对高程估计”是指高程范围,尽管对于线串来说它可以是多个指标。使用

sf
时,线串长度有点微不足道:
st_length()
;为了构建这些线串,也许首先尝试 dplyer-style
group()
+
summarise()
,如果由于点数而证明它不切实际,您可以考虑替代方案。

library(elevatr)
library(dplyr)
library(sf)
#> Linking to GEOS 3.11.2, GDAL 3.6.2, PROJ 9.2.0; sf_use_s2() is TRUE

aus_sf <-
  aus |>
  # make sure points are correctyl sorted
  arrange(country, id, point_id) |>
  # convert to sf object
  st_as_sf(coords = c("lon", "lat"), crs = "WGS84") |>
  # get elevation from Amazon Web Service Terrain Tiles
  get_elev_point(src = "aws")
  
aus_sf
#> Simple feature collection with 17 features and 5 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 129.251 ymin: -20.06129 xmax: 137.2865 ymax: -18.30723
#> Geodetic CRS:  WGS 84
#> First 10 features:
#>    id   country point_id                   geometry elevation elev_units
#> 1   1 Australia        0  POINT (130.1491 -19.5752)       382     meters
#> 2   1 Australia        1  POINT (129.9958 -19.4876)       425     meters
#> 3   1 Australia        2 POINT (129.7156 -19.25788)       444     meters
#> 4   1 Australia        3 POINT (129.7104 -19.20223)       441     meters
#> 5   2 Australia        0  POINT (129.251 -18.59016)       376     meters
#> 6   2 Australia        1 POINT (129.5436 -18.30723)       398     meters
#> 7   3 Australia        0  POINT (137.284 -20.06129)       229     meters
#> 8   3 Australia        1 POINT (137.2865 -20.04308)       234     meters
#> 9   3 Australia        2 POINT (137.1915 -20.00782)       237     meters
#> 10  3 Australia        3  POINT (137.122 -19.97166)       234     meters

从有序点构建线串:

aus_lines <- 
  aus_sf |>
  # group by `country` to keep it as attribute and by `id` 
  # to create 4 multipoints, one per id
  group_by(country, id) |>
  # points to multipoints, 
  # do not use do_union as it will likely change point order,
  # add elevation range
  summarise(elev_range = max(elevation) - min(elevation), do_union = FALSE, .groups = "drop") |>
  # multipoints to linestrings
  st_cast("LINESTRING") |>
  # add length column
  mutate(length = st_length(geometry))

生成的具有高程范围和长度的线串:

aus_lines
#> Simple feature collection with 4 features and 4 fields
#> Geometry type: LINESTRING
#> Dimension:     XY
#> Bounding box:  xmin: 129.251 ymin: -20.06129 xmax: 137.2865 ymax: -18.30723
#> Geodetic CRS:  WGS 84
#> # A tibble: 4 × 5
#>   country      id elev_range                                     geometry length
#> * <chr>     <int>      <dbl>                             <LINESTRING [°]>    [m]
#> 1 Australia     1         62 (130.1491 -19.5752, 129.9958 -19.4876, 129.… 63941.
#> 2 Australia     2         22      (129.251 -18.59016, 129.5436 -18.30723) 44072.
#> 3 Australia     3          8 (137.284 -20.06129, 137.2865 -20.04308, 137… 48462.
#> 4 Australia     4          4 (136.8961 -19.85932, 136.8791 -19.88669, 13… 10190.

数据集示例:

aus <- read.table(header = TRUE, text =
"id   country point_id      lon       lat
  1  Australia        0 130.1491 -19.57520
  1  Australia        1 129.9958 -19.48760
  1  Australia        2 129.7156 -19.25788
  1  Australia        3 129.7104 -19.20223
  2  Australia        0 129.2510 -18.59016
  2  Australia        1 129.5436 -18.30723
  3  Australia        0 137.2840 -20.06129
  3  Australia        1 137.2865 -20.04308
  3  Australia        2 137.1915 -20.00782
  3  Australia        3 137.1220 -19.97166
  3  Australia        4 137.0650 -19.91363
  3  Australia        5 136.8961 -19.85932
  4  Australia        0 136.8961 -19.85932
  4  Australia        1 136.8791 -19.88669
  4  Australia        2 136.8594 -19.91227
  4  Australia        3 136.8454 -19.92507
  4  Australia        4 136.8360 -19.92976")
© www.soinside.com 2019 - 2024. All rights reserved.