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)))
ahmadhanb
41.8k5 gold badges55 silver badges109 bronze badges
asked Jan 27, 2017 at 2:51

3 Answers 3

6

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.

answered Feb 6, 2017 at 14:55
1
  • 1
    st_join is now in the released CRAN version Commented Feb 6, 2018 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
answered Jan 27, 2017 at 8:46
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
answered Jan 29, 2017 at 12:56

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.