更新 sf linestring 对象的起始和结束坐标。

3

我有一个包含LINESTRING几何图形的大型sf-object(约100000行)。我想要更改每个linestring的第一个和最后一个坐标/点。

我知道可以通过将linestrings转换为points来实现此目的,更改每个linestring id的第一行/点和最后一行/点的几何图形,然后再将其转换回linestring。但这似乎需要很多额外的(不必要的?)步骤和计算。我有一种感觉,这可以用更直接的方式完成...但我不知道如何做。

library(sf)
library(tidyverse)

#sample data
mypoints <- data.frame(id = 1, lon = 1:5, lat = 1:5)

line1 <- mypoints %>% 
  st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
  dplyr::group_by(id) %>% 
  dplyr::summarise() %>% 
  st_cast("LINESTRING") 

# desired output
# change first coordinate of line from (1,1) to (1,2), 
# and last coordinate from (5,5) to (5,4)
# so in the end, line 1 should look like line2
mypoints2 <- data.frame(id = 1, lon = c(1:5), lat = c(2,2:4,4))

line2 <- mypoints2 %>% 
  st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
  dplyr::group_by(id) %>% 
  dplyr::summarise() %>% 
  st_cast("LINESTRING")

# old = blue, new = red
ggplot() + 
  geom_sf(data = line1, color = "blue", linewidth  = 6) +
  geom_sf(data = line2, color = "red", linewidth  = 3)

enter image description here

我的当前方法:

# cast LINESTRINGs to POINTs
line2 <- line1 %>% st_cast("POINT")

# create sf object with net start ans endpoints
new_start_end <- data.frame(id = c("first", "last"), 
                            lon = c(1,5),
                            lat = c(2,4)) %>% 
                       st_as_sf(coords = c("lon", "lat"), crs = 4326)
# set first and last value of geometry to new values
st_geometry(line2[c(1,nrow(line2)),]) <- st_geometry(new_start_end)

line2 %>% 
  dplyr::group_by(id) %>% 
  dplyr::summarise() %>% 
  st_cast("LINESTRING")
# Simple feature collection with 1 feature and 1 field
# Geometry type: LINESTRING
# Dimension:     XY
# Bounding box:  xmin: 1 ymin: 2 xmax: 5 ymax: 4
# Geodetic CRS:  WGS 84
# # A tibble: 1 × 2
#        id                  geometry
#     <dbl>          <LINESTRING [°]>
#   1     1 (1 2, 2 2, 3 3, 4 4, 5 4)

你好!你能否提供更多关于你想如何改变这两个点的细节呢?你想用新的点来替换它们还是总是应用固定的平移? - agila
理想情况下,我希望能够用新的坐标替换每个线串的第一个和最后一个点。 - Wimpel
1个回答

1

这里有一种通过purrr :: modify实现的方法。您可以在自定义函数中更改所需的修改方式。

设置

library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
library(tidyverse)

# CHANGED sample data -> poc that it works with multiple lines as well
mypoints <- data.frame(id = c(rep(1:2, 5)), lon = 1:10, lat = 1:10)

line12 <- mypoints %>% 
  st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
  dplyr::group_by(id) %>% 
  dplyr::summarise() %>% 
  st_cast("LINESTRING") 

解决方案

# example modification: replace first and last value with 0
modify_fun <- function(g) {
  g[c(1, length(g))] <- c(0,0)
  return(g)
}

# keep old object for comparison
line12_mod <- line12

# modify lines
line12_mod$geometry <- purrr::modify(line12$geometry, .f = modify_fun)
line12_mod
#> Simple feature collection with 2 features and 1 field
#> Geometry type: LINESTRING
#> Dimension:     XY
#> Bounding box:  xmin: 1 ymin: 1 xmax: 10 ymax: 10
#> Geodetic CRS:  WGS 84
#> # A tibble: 2 × 2
#>      id                   geometry
#> * <int>           <LINESTRING [°]>
#> 1     1  (0 1, 3 3, 5 5, 7 7, 9 0)
#> 2     2 (0 2, 4 4, 6 6, 8 8, 10 0)

绘图

ggplot() + 
  geom_sf(data = line12,     color = "blue", linewidth = 6) +
  geom_sf(data = line12_mod, color = "red",  linewidth = 3)

enter image description here


这里出错了。
line12_mod$geometry <- purrr::modify(line12$geometry, .f = modify_fun) map_vec() 出错: !out[[1]] 的大小必须为1,而不是5。
- undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接