简体   繁体   English

更新 sf linestring 的(第一个和最后一个)坐标 object

[英]update (first and last) coordinates of sf linestring object

I have a large sf-object with LINESTRING-geometry (~ 100000 rows).我有一个带有 LINESTRING 几何(~ 100000 行)的大型 sf 对象。 Of this object, I want to change the first and last coordinate/point of each linestring.在这个 object 中,我想更改每个线串的第一个和最后一个坐标/点。

I know I can do this by casting the linestrings to points, change the geometry of the first and last row/point of each linestring id, and the cast back to linestring.我知道我可以通过将线串转换为点,更改每个线串 ID 的第一行和最后一行/点的几何形状,然后转换回线串来做到这一点。 But this seems like a lot of extra (unnecessairy?) steps and calculations.但这似乎有很多额外的(不必要的?)步骤和计算。 I have got a feeling this can be done in a more direct way... but I don't know how.我觉得这可以用更直接的方式来完成……但我不知道该怎么做。

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)

在此处输入图像描述

my current method:我目前的方法:

# 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)

Here is a way to do this via purrr::modify .这是通过purrr::modify执行此操作的一种方法。 You can change the desired way of modification in the custom function.可以在自定义function中更改自己想要的修改方式。

Setup设置

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") 

Solution解决方案

# 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)

Plot Plot

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

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM