5

I have a dataset of POINTS with Z values and I would like to convert it to a MULTIPOINT dataset grouped by ID

I used the code from Converting points to polygons by group and it successfully grouped my points to multipoint but it dropped the z value.

Here is the code from the top answer of the other question which I based my own on:

set.seed(999)
xy = data.frame(x=runif(24), y=runif(24))
xy$ID = rep(1:6, each = 4)
head(xy)

xys = st_as_sf(xy, coords=c("x","y"))

polys = xys %>% dplyr::group_by(ID) %>% dplyr::summarise() %>% st_cast("POLYGON")

plot(polys)

Here is what I actually used on my data

lsp_mp2 <- lsp %>%
  dplyr::group_by(lsp$ID) %>%
  dply::summarise() %>%
  st_cast('MULTIPOINT')

How do I retain the Z value?

There is a column in my data with a Z value. The output of this function gave me an attribute table with only one column. All of the other columns were lost with this function.

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
nerdsconsider
  • 379
  • 1
  • 8

2 Answers2

7

Make a spatial sample data set with xyz geometry and an ID column:

d = data.frame(x=runif(20),y=runif(20),z=runif(20),id=sample(1:3,20,TRUE))
sd = st_as_sf(d, coords=1:3)

split it by the ID:

sdsplit = split(sd, sd$id)

run st_combine on each element:

sdcombine = Map(st_combine, sdsplit)

and join them all together:

sdset = do.call(c, sdcombine)

giving MULTIPOINT geometries for the ID groupings with XYZ preserved

> sdset
Geometry set for 3 features 
Geometry type: MULTIPOINT
Dimension:     XYZ
Bounding box:  xmin: 0.0440282 ymin: 0.03704024 xmax: 0.9970125 ymax: 0.9578563
z_range:       zmin: 0.3112239 zmax: 0.7384504
CRS:           NA
MULTIPOINT Z ((0.2610551 0.9356371 0.3112239), ...
MULTIPOINT Z ((0.7179385 0.3060261 0.0004098632...
MULTIPOINT Z ((0.8213335 0.3986064 0.8561131), ...

And if you want that as a one-liner (and I'll use Reduce instead of do.call for no good reason):

sdset = Reduce(c, Map(st_combine,split(sd,sd$id)))

Only uses base packages and sf.

Spacedman
  • 63,755
  • 5
  • 81
  • 115
3

I believe you are looking for sf::st_combine() function, though the grouping muddles the waters somewhat.

For an ungrouped example consider this piece of code (note that the Z dimension works the best for points, while your sample code uses polygons; as a result I resort to my own favorite set of points - three semi-random cities in North Carolina, to make use of the wildly popular nc.shp shapefile).

Also note that the most typical use case of Z dimension is height; I am using population instead, as that is what I had the most easily available (see https://stackoverflow.com/questions/69796519/adjust-centroids-spatial-polygons-using-sf). It should have little effect on the output.

library(sf)
library(dplyr)

shape <- st_read(system.file("shape/nc.shp", package="sf")) # included with sf package

cities <- data.frame(name = c("Raleigh", "Greensboro", "Wilmington"), x = c(-78.633333, -79.819444, -77.912222), y = c(35.766667, 36.08, 34.223333), population = c(467665, 299035, 115451)) %>% st_as_sf(coords = c("x", "y", "population"), crs = 4326, dim = "XYZ")

result <- cities %>% st_combine()

result

Geometry set for 1 feature

Geometry type: MULTIPOINT

Dimension: XYZ

Bounding box: xmin: -79.81944 ymin: 34.22333 xmax: -77.91222 ymax: 36.08

z_range: zmin: 115451 zmax: 467665

Geodetic CRS: WGS 84

MULTIPOINT Z ((-78.63333 35.76667 467665), (-79...

Jindra Lacko
  • 1,090
  • 6
  • 11