I have the following dataframe with an ID column and XY point coordinates. It's a simple case with only two points per line (dataframe only has ID pairs):
data <- data.frame(
id = c("1C1", "1C1", "1C2", "1C2"),
X = c(666427.3830, 666440.9899, 666375.8780, 666365.8079),
Y = c(4681239.659, 4681239.3219,4680517.0930, 4680526.1789))
Each ID is duplicated because it points to the start and end of a line. I have created an R script to perform the following steps with the sf
package:
- Filter the dataframe by ID
- Create a
LINESTRING
geometry object - Find each centroid
- Store the ID and its centroid point in a new dataframe
library(sf)
points <- st_as_sf(data, coords = c('X', 'Y'), crs = 25830)
# Get unique IDs
ids <- levels(as.factor(points$id))
# Apply a function to get points from the above IDs and
# create a LINESTRING object
makeLine <- function(id){
# Select two points (start and end) by ID
ps <- points[points$id == id,]
# Create a Linestring geometry object
geo <- st_cast(st_union(ps[1, 'geometry'], ps[2, 'geometry']), "LINESTRING")
return(geo)
}
# Get lines by points
lines <- lapply(ids, makeLine)
# Unlist values to extract the sf geometry objects
lines_ <- do.call(c, unlist(lines, recursive=FALSE))
# Save centroids
centroids <- st_centroid(lines_)
# Create a new sf object with centroids and their IDs
points_c <- st_as_sf(data.frame(ids = ids, centroids))
plot(points_c)
Is there a better way to achieve the above result in R?
I know that in this GIS StackExchange post and in this one there are approaches to do these operations, but I want to perform the analysis in R. This post to create a line by 2 geometry columns in the same dataframe gave me some inspiration.
R version 4.3.3 (2024-02-29 ucrt)
sf version 1.0-16