8

I want to spatial join with SpatialPolygonsDataFrame and SpatialPointsDataFrame.

get only one point data within multiple polygons, under the code.

sp::over(meuse, srdf)

Some points data into multiple Polygons. I want to get points data keep all the polygon data.

for example: point A within polygon a and b.

now can get:

| point | polygon |
-------------------
| A     | a       |

I get like this:

| point | polygon |
-------------------
| A     | a       |
| A     | b       |

Use data:

    coordinates(meuse) = ~x+y
    sr1=Polygons(list(Polygon(cbind(c(180114, 180553, 181127, 181477, 181294, 181007, 180409,
                                      180162, 180114), c(332349, 332057, 332342, 333250, 333558, 333676,
                                                         332618, 332413, 332349)))),'1')
    sr2=Polygons(list(Polygon(cbind(c(180042, 180545, 180553, 180314, 179955, 179142, 179437,
                                      179524, 179979, 180042), c(332373, 332026, 331426, 330889, 330683,
                                                                 331133, 331623, 332152, 332357, 332373)))),'2')
    sr3=Polygons(list(Polygon(cbind(c(179110, 179907, 180433, 180712, 180752, 180329, 179875,
                                      179668, 179572, 179269, 178879, 178600, 178544, 179046, 179110),
                                    c(331086, 330620, 330494, 330265, 330075, 330233, 330336, 330004,
                                      329783, 329665, 329720, 329933, 330478, 331062, 331086)))),'3')
    sr4=Polygons(list(Polygon(cbind(c(180304, 180403,179632,179420,180304),
                                    c(332791, 333204, 333635, 333058, 332791)))),'4')
    sr5=Polygons(list(Polygon(cbind(c(179500, 180000, 180000, 179500),
                                    c(331000, 331000, 331500, 331500)))), '5')
    sr=SpatialPolygons(list(sr1,sr2,sr3,sr4, sr5))
    srdf=SpatialPolygonsDataFrame(sr, data.frame(row.names=c('1','2','3','4', '5'), PIDS=1:5, y=runif(5)))
5

The st_join function in the sf package (development version) provides a simple and intuitive solution. It returns the spatial join as a data.frame, and you can easily convert back to Spatial*.

# Convert to sf-objects
srdf.sf <- st_as_sf(srdf)
meuse.sf <- st_as_sf(meuse)

# Keep all "meuse.sf", sort by row.names(meuse.sf). Default overlay is "intersects".
meuse_srdf <- st_join(meuse.sf, srdf.sf) 

# Keeps all "srdf.sf", sort by row.names(srdf.sf)
srdf_meuse <- st_join(srdf.sf, meuse.sf)

# Convert back to Spatial*
meuse_srdf <- as(meuse_srdf, "Spatial")
srdf_meuse <- as(srdf_meuse, "Spatial")

EDIT:

st_join is now in the CRAN version of sf, as previously pointed out by SymbolixAU.

  • 1
    st_join is now in the released CRAN version – SymbolixAU Feb 6 '18 at 0:21
4

Use over(meuse, srdf, returnList=TRUE)

 if ‘returnList’ is TRUE, a list of length
 ‘length(x)’, with list element ‘i’ the vector of all indices of
 the geometries in ‘y’ that correspond to the $i$-th geometry in
 ‘x’.

First point overlays one polygon, 135th point overlays two:

> rr = over(meuse,srdf,returnList=TRUE)
> rr[[1]]
  PIDS         y
1    1 0.2069365
> rr[[135]]
  PIDS          y
2    2 0.34809708
5    5 0.08942346

Note if you only want the overlaid polygon indexes and not all the attributes, just convert the polygons to SpatialPolygons and you get back a list of index numbers rather than data frames with all the attributes in:

> rr = over(meuse,as(srdf,"SpatialPolygons"),returnList=TRUE)
> rr[[1]]
[1] 1
> rr[[135]]
[1] 2 5
0

I can get data.frame under the code:

library(tidyverse)
sp::over(meuse, srdf, returnList=TRUE) %>%
plyr::ldply(., data.frame) -> tmp

It's auto added .id column.
If get filtered or edited meuse data, do under the code.

use_id <- 
  tmp %>% select(`.id`) %>% unlist(., use.names = F)
rownames(meuse) %in% use_id

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.