I have a df with polygon ID's from a shapefile and their centre-points in a geometry column:
# A tibble: 3 x 2
ID geometry
<dbl> <POINT [°]>
1 1 (117.2 31.8)
2 2 (116.4 40.1)
3 4 (117.9 26)
I want to put the latitude/longitude values into separate columns, so I do:
library(sf)
centres<- as.data.frame(st_coordinates(df))
This new 'centres' dataframe has the lat&long values, but misses the ID column. How can I preserve it, or is there another way to get the lat&long values into separate columns from the geometry column whilst keeping the ID in the same df?
dput for the dataframe is:
df <- structure(list(ID = c(1, 2, 4),
geometry = structure(list(structure(c(117.2, 31.8),
class = c("XY", "POINT", "sfg")), structure(c(116.4, 40.1),
class = c("XY", "POINT", "sfg")), structure(c(117.9, 26.0),
class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", "sfc"),
precision = 0, bbox = structure(c(xmin = 116.4, ymin = 26.0, xmax = 117.9, ymax = 40.1),
class = "bbox"), crs = structure(list(epsg = 4326L,
proj4string = "+proj=longlat +datum=WGS84 +no_defs"), class = "crs"), n_empty = 0L)),
row.names = c(NA, -3L), class = c("sf", "tbl_df", "tbl", "data.frame"),
sf_column = "geometry", agr = structure(c(ID = NA_integer_),
class = "factor", .Label = c("constant", "aggregate", "identity")))
Solution using unlist + map()
library(tidyverse)
separated_coord <- df %>%
mutate(lat = unlist(map(df$geometry,1)),
long = unlist(map(df$geometry,2)))
separated_coord
st_geometry
can be used with dplyr::mutate
:
library(magrittr) #for the pipe
df <- df %>%
dplyr::mutate(lon = sf::st_coordinates(.)[,1],
lat = sf::st_coordinates(.)[,2])
df
Simple feature collection with 3 features and 3 fields
geometry type: POINT
dimension: XY
bbox: xmin: 116.4 ymin: 26 xmax: 117.9 ymax: 40.1
CRS: EPSG:4326
# A tibble: 3 x 4
ID geometry lon lat
* <dbl> <POINT [°]> <dbl> <dbl>
1 1 (117.2 31.8) 117. 31.8
2 2 (116.4 40.1) 116. 40.1
3 4 (117.9 26) 118. 26
And if you no longer care about geometry
, transform in a standard dataframe using df %>% sf::st_set_geometry(NULL)
A possible approach is to unlist it.
setNames(data.frame(df[[1]],
matrix(unlist(df[2]), ncol=2, byrow=TRUE)),
c("ID", "lon", "lat"))
# ID lon lat
# 1 1 117.2 31.8
# 2 2 116.4 40.1
# 3 4 117.9 26.0
Explanation
Data structure check with str(df)
shows, that a variable - geometry
- is in list
format, which can be unhandy. A way to solve this is to unlist()
it, transform it into a 2-column matrix, and reassemble it with the first column. With setNames()
we are able to assign new column names in one step.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With