[英]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中更改自己想要的修改方式。
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.