Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
595 views
in Technique[技术] by (71.8m points)

r - How to find which polygon a point belong to via sf

I have a sf object that contains polygon information (precincts) for a metro area, obtained through a .shp file. For a given lat/lon pair, I want to determine which precinct it belongs to. I'm thinking I can utilize sf::st_contains() but am having trouble getting the lat/lon in the right format.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This can be "vectorized". Here's an example:

library(sf)
library(tidyverse)

Singapore shapefile:

singapore <- st_read("~/data/master-plan-2014-subzone-boundary-no-sea-shp/MP14_SUBZONE_NO_SEA_PL.shp", quiet=TRUE, stringsAsFactors=FALSE)
singapore <- st_transform(singapore, 4326)

CSV of recycling centers:

centers <- read_csv("~/data/recycl.csv")
glimpse(centers)
## Observations: 407
## Variables: 10
## $ lng             <dbl> 104.0055, 103.7677, 103.7456, 103.7361, 103.8106, 103.962...
## $ lat             <dbl> 1.316764, 1.296245, 1.319204, 1.380412, 1.286512, 1.33355...
## $ inc_crc         <chr> "F8907D68D7EB64A1", "ED1F74DC805CEC8B", "F48D575631DCFECB...
## $ name            <chr> "RENEW (Recycling Nation's Electronic Waste)", "RENEW (Re...
## $ block_house_num <chr> "10", "84", "698", "3", "2", "1", "1", "1", "357", "50", ...
## $ bldg_name       <chr> "Changi Water Reclamation Plant", "Clementi Woods", "Comm...
## $ floor           <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ post_code       <int> 498785, 126811, 608784, 689814, 159047, 486036, 39393, 55...
## $ street          <chr> "Changi East Close", "West Coast Road , Clementi Woods Co...
## $ unit            <chr> "(Lobby)", "#B1-01 (Management Office)", "(School foyer)"...

Turn ^^ into a simple features object:

map2(centers$lng, centers$lat, ~st_point(c(.x, .y))) %>% 
  st_sfc(crs = 4326) %>% 
  st_sf(centers[,-(1:2)], .) -> centers_sf

This is likely faster than the row-wise op but I'll let someone else have fun benchmarking:

bind_cols(
  centers,
  singapore[as.numeric(st_within(centers_sf, singapore)),]
) %>% 
  select(lng, lat, inc_crc, subzone_name=SUBZONE_N) %>% 
  mutate(subzone_name = str_to_title(subzone_name))
## # A tibble: 407 x 4
##         lng      lat          inc_crc               subzone_name
##       <dbl>    <dbl>            <chr>                      <chr>
##  1 104.0055 1.316764 F8907D68D7EB64A1             Changi Airport
##  2 103.7677 1.296245 ED1F74DC805CEC8B             Clementi Woods
##  3 103.7456 1.319204 F48D575631DCFECB              Teban Gardens
##  4 103.7361 1.380412 1F910E0086FD4798                 Peng Siang
##  5 103.8106 1.286512 55A0B9E7CBD34AFE             Alexandra Hill
##  6 103.9624 1.333555 C664D09D9CD5325F                      Xilin
##  7 103.8542 1.292778 411F79EAAECFE609                  City Hall
##  8 103.8712 1.375876 F4516742CFD4228E Serangoon North Ind Estate
##  9 103.8175 1.293319 B05B32DF52D922E7            Alexandra North
## 10 103.9199 1.335878 58E9EAF06206C772            Bedok Reservoir
## # ... with 397 more rows

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...