[英]Create buffer around spatial point data in R and count how many points are in the buffer
[英]R | sf: I have points and 2 buffers around each point. How to combine the points into single units if larger buffer overlaps (but smaller does not)?
我目前在地圖(學校)上有點。 每個點(學校)周圍都有兩個緩沖區。 一種是 450m,一種是 250m。 如果點重疊,我想將它們視為一個單元(因為否則事情會變得復雜),但我希望它們保持它們覆蓋的幾何形狀/區域。
因此,在此處給出的示例地圖上,我希望將前三所學校/點合並為一個“單元”。 我希望他們保留他們覆蓋的區域,但只需將 R 視為一個單位。 如果我使用“st_union”函數,我必須對較小和較大的緩沖區都這樣做。 但這會導致單元總數的差異,因為更多的較大緩沖區重疊。 所以基本上我希望較小的緩沖區與其他較小的緩沖區合並(合並為一個單元),如果較大的緩沖區重疊並因此合並。
最終目標是我想計算一家商店在距離學校 250m 以內與 450m 相比有多少次。 我認為,由於學校之間的大量重疊,如上所述最容易合並。
我的代碼如下,但請注意,由於上述原因,它會導致學校/單位數量不同。
county.sf <- get_acs(state = "MO",
county = c( "St. Louis City"),
geography = "tract",
variables = "B03002_001",
output="wide",
geometry = TRUE) %>%
sf::st_transform(crs = "ESRI:102003")
class(county.sf)
# School data
school <- read.csv("C:\\myfile1.csv")
school.sf <- st_as_sf(school, coords = c("long", "lat"), crs = "epsg:4326")
school.sf.utm <- st_transform(school.sf, crs = "ESRI:102003")
# Store data
store <- import("C:\\myfile2.csv")
store.sf <- st_as_sf(store, coords = c("XCoord", "YCoord"), crs = "ESRI:102696")
store.sf.utm <- st_transform(store.sf, crs = "ESRI:102003")
elem.buff <-st_buffer(school.sf.utm, 250)
elem.buff2 <-st_buffer(school.sf.utm, 450)
pts_com<-st_union(elem.buff)
pts_pol<-st_cast(pts_com, "POLYGON")
pts_com2<-st_union(elem.buff2)
pts_pol2<-st_cast(pts_com2, "POLYGON")
#unmerged zone map
ex.map<- tm_shape(county.sf) +
tm_polygons() +
tm_shape(elem.buff) +
tm_borders(col="red") +
tm_shape(school.sf.utm) +
tm_dots(col = "red") +
tm_shape(elem.buff2) +
tm_borders(col="blue") +
tm_shape(pts_pol) +
tm_borders(col="black") +
tm_shape(store.sf.utm) +
tm_dots()
ex.map
#merged zones map
ex.map<- tm_shape(county.sf) +
tm_polygons() +
#(elem.buff) +
#tm_borders(col="red") +
tm_shape(school.sf.utm) +
tm_dots(col = "red") +
#tm_shape(elem.buff2) +
#tm_borders(col="blue") +
tm_shape(pts_pol) +
tm_borders(col="red") +
tm_shape(store.sf.utm) +
tm_dots() +
tm_shape(pts_pol2) +
tm_borders(col="blue")
ex.map
lengths(st_intersects(elem.buff, store.sf.utm)) #gives per school but ignores overlapping
lengths(st_intersects(pts_pol, store.sf.utm))
lengths(st_intersects(elem.buff2, store.sf.utm)))
lengths(st_intersects(pts_pol2, store.sf.utm)))
最初我建議使用st_intersection()
,但這開始變得復雜,所以我使用了這種方法,而不是依賴於st_join()
。
首先,加載庫和數據。
library(readxl)
library(tidyverse)
library(sf)
library(tmap)
tmap_mode('view')
read_xlsx('Schools and Stores_all.xlsx', sheet = 1) %>%
st_as_sf(., coords = c("long", "lat"), crs = "epsg:4326") %>%
st_transform(crs = "ESRI:102003") %>%
{. ->> schools}
schools
# Simple feature collection with 156 features and 1 field
# Geometry type: POINT
# Dimension: XY
# Bounding box: xmin: 208163.7 ymin: -81868.36 xmax: 565039.3 ymax: 151922.7
# Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic
# # A tibble: 156 x 2
# School geometry
# * <chr> <POINT [m]>
# 1 AcademyOf Envt Sci/math Elementary School (497569.1 143116)
# 2 AcademyOf Envt Sci/math Middle School (498610.1 140067.7)
# 3 Adams Elementary School (495000.6 141023.2)
# 4 Ames Visual/perf. Arts (500120.2 144483.3)
# 5 Ashland Elementary And Br. (496514.9 146392.7)
# 6 Aspire Academy (495458 149014.6)
# 7 Beaumont Cte High School (497748.6 145417.7)
# 8 Bryan Hill Elementary School (495926.2 144709.6)
# 9 Buder Elementary School (492994.6 136888.8)
# 10 Busch Ms Character Athletics (491906.9 135569.1)
# # ... with 146 more rows
然后,在學校周圍建立緩沖區。
schools %>%
st_buffer(250) %>%
{. ->> schools_250}
schools_250
# Simple feature collection with 156 features and 1 field
# Geometry type: POLYGON
# Dimension: XY
# Bounding box: xmin: 207913.7 ymin: -82118.36 xmax: 565289.3 ymax: 152172.7
# Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic
# # A tibble: 156 x 2
# School geometry
# * <chr> <POLYGON [m]>
# 1 AcademyOf Envt Sci/math Elementary School ((497819.1 143116, 497818.8 143103, 497817.7 143089.9, 497816 ~
# 2 AcademyOf Envt Sci/math Middle School ((498860.1 140067.7, 498859.7 140054.7, 498858.7 140041.6, 498~
# 3 Adams Elementary School ((495250.6 141023.2, 495250.3 141010.1, 495249.3 140997, 49524~
# 4 Ames Visual/perf. Arts ((500370.2 144483.3, 500369.9 144470.2, 500368.9 144457.2, 500~
# 5 Ashland Elementary And Br. ((496764.9 146392.7, 496764.6 146379.6, 496763.6 146366.5, 496~
# 6 Aspire Academy ((495708 149014.6, 495707.6 149001.5, 495706.6 148988.4, 49570~
# 7 Beaumont Cte High School ((497998.6 145417.7, 497998.3 145404.7, 497997.3 145391.6, 497~
# 8 Bryan Hill Elementary School ((496176.2 144709.6, 496175.9 144696.5, 496174.9 144683.5, 496~
# 9 Buder Elementary School ((493244.6 136888.8, 493244.2 136875.7, 493243.2 136862.7, 493~
# 10 Busch Ms Character Athletics ((492156.9 135569.1, 492156.6 135556, 492155.5 135543, 492153.~
# # ... with 146 more rows
schools %>%
st_buffer(450) %>%
{. ->> schools_450}
schools_450
# Simple feature collection with 156 features and 1 field
# Geometry type: POLYGON
# Dimension: XY
# Bounding box: xmin: 207713.7 ymin: -82318.36 xmax: 565489.3 ymax: 152372.7
# Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic
# # A tibble: 156 x 2
# School geometry
# * <chr> <POLYGON [m]>
# 1 AcademyOf Envt Sci/math Elementary School ((498019.1 143116, 498018.5 143092.5, 498016.7 143069, 498013.~
# 2 AcademyOf Envt Sci/math Middle School ((499060.1 140067.7, 499059.5 140044.2, 499057.6 140020.7, 499~
# 3 Adams Elementary School ((495450.6 141023.2, 495450 140999.6, 495448.2 140976.1, 49544~
# 4 Ames Visual/perf. Arts ((500570.2 144483.3, 500569.6 144459.8, 500567.8 144436.3, 500~
# 5 Ashland Elementary And Br. ((496964.9 146392.7, 496964.3 146369.1, 496962.5 146345.6, 496~
# 6 Aspire Academy ((495908 149014.6, 495907.4 148991, 495905.5 148967.5, 495902.~
# 7 Beaumont Cte High School ((498198.6 145417.7, 498198 145394.2, 498196.2 145370.7, 49819~
# 8 Bryan Hill Elementary School ((496376.2 144709.6, 496375.6 144686.1, 496373.8 144662.6, 496~
# 9 Buder Elementary School ((493444.6 136888.8, 493444 136865.2, 493442.1 136841.8, 49343~
# 10 Busch Ms Character Athletics ((492356.9 135569.1, 492356.3 135545.5, 492354.4 135522, 49235~
# # ... with 146 more rows
使用st_union()
加入所有 450 m 緩沖區,以確定“單位”的身份。
schools_450 %>%
st_union %>%
st_cast('POLYGON') %>%
st_sf %>%
mutate(
unit = row_number()
) %>%
{. ->> schools_450_units}
schools_450_units
# Simple feature collection with 39 features and 1 field
# Geometry type: POLYGON
# Dimension: XY
# Bounding box: xmin: 207713.7 ymin: -82318.36 xmax: 565489.3 ymax: 152372.7
# Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic
# First 10 features:
# geometry unit
# 1 POLYGON ((565450.4 -82051.3... 1
# 2 POLYGON ((499821.5 138524.2... 2
# 3 POLYGON ((498299.1 138974.4... 3
# 4 POLYGON ((500735.6 142090.4... 4
# 5 POLYGON ((499872.4 142927.1... 5
# 6 POLYGON ((496870.2 135641.5... 6
# 7 POLYGON ((495561.7 135210, ... 7
# 8 POLYGON ((498291.9 141786.4... 8
# 9 POLYGON ((496337.3 144526.6... 9
# 10 POLYGON ((208574.8 -53382.3... 10
請注意,在 156 所學校中,我們只有 39 個單元。 當然,當多個 450 m 緩沖區鏈接在一起時,這些單元的范圍可能會很遠 - 請參閱最后的地圖。
然后,我們使用st_join()
來確定每個單元內有哪些學校(或其緩沖區)。 指定join = st_within
是這里的關鍵。
schools %>%
st_join(schools_450_units, join = st_within) %>%
{. ->> schools_units}
schools_units
# Simple feature collection with 156 features and 2 fields
# Geometry type: POINT
# Dimension: XY
# Bounding box: xmin: 208163.7 ymin: -81868.36 xmax: 565039.3 ymax: 151922.7
# Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic
# # A tibble: 156 x 3
# School geometry unit
# * <chr> <POINT [m]> <int>
# 1 AcademyOf Envt Sci/math Elementary School (497569.1 143116) 5
# 2 AcademyOf Envt Sci/math Middle School (498610.1 140067.7) 3
# 3 Adams Elementary School (495000.6 141023.2) 3
# 4 Ames Visual/perf. Arts (500120.2 144483.3) 5
# 5 Ashland Elementary And Br. (496514.9 146392.7) 32
# 6 Aspire Academy (495458 149014.6) 37
# 7 Beaumont Cte High School (497748.6 145417.7) 33
# 8 Bryan Hill Elementary School (495926.2 144709.6) 9
# 9 Buder Elementary School (492994.6 136888.8) 18
# 10 Busch Ms Character Athletics (491906.9 135569.1) 13
# # ... with 146 more rows
然后要將同一單元的 250 m 緩沖區(即使它們沒有接觸)合並為一個MULTIPOLYGON
,我們使用group_by(unit)
並使用summarise(do_union = TRUE)
(默認值)。 這類似於st_union()
,但尊重group_by()
(實際上可能使用st_union()
獲得完全相同的結果,但這也有效)。
schools_units %>%
`st_geometry<-`(schools_250 %>% st_geometry) %>%
group_by(unit) %>%
summarise(do_union = TRUE) %>%
{. ->> schools_250_units}
schools_250_units
# Simple feature collection with 39 features and 1 field
# Geometry type: GEOMETRY
# Dimension: XY
# Bounding box: xmin: 207913.7 ymin: -82118.36 xmax: 565289.3 ymax: 152172.7
# Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic
# # A tibble: 39 x 2
# unit geometry
# <int> <GEOMETRY [m]>
# 1 1 POLYGON ((565289.3 -81868.36, 565289 -81881.45, 565288 -81894.49, 565286.2 -81907.47, 565283.9 -8...
# 2 2 MULTIPOLYGON (((499659 138681.1, 499657.3 138668.1, 499654.9 138655.3, 499651.9 138642.5, 499648....
# 3 3 MULTIPOLYGON (((496446.7 137764.8, 496442.9 137752.3, 496438.6 137739.9, 496433.6 137727.9, 49642...
# 4 4 MULTIPOLYGON (((500574.2 142260.4, 500573.1 142247.3, 500571.4 142234.4, 500569 142221.5, 500566 ...
# 5 5 MULTIPOLYGON (((497408.5 142703.5, 497404.7 142690.9, 497400.4 142678.6, 497395.4 142666.5, 49738...
# 6 6 MULTIPOLYGON (((496993.6 135888.6, 496982.8 135881.2, 496971.6 135874.4, 496960.1 135868.1, 49694...
# 7 7 MULTIPOLYGON (((496252.1 134426.9, 496250.4 134413.9, 496248 134401.1, 496244.9 134388.3, 496241....
# 8 8 POLYGON ((498130.8 141969.4, 498130.4 141956.3, 498129.4 141943.3, 498127.7 141930.3, 498125.3 14...
# 9 9 MULTIPOLYGON (((496175.9 144696.5, 496174.9 144683.5, 496173.1 144670.5, 496170.8 144657.6, 49616...
# 10 10 POLYGON ((208413.7 -53199.34, 208413.3 -53212.42, 208412.3 -53225.47, 208410.6 -53238.45, 208408....
# # ... with 29 more rows
希望這已經回答了您的問題,因為現在我們有:
schools_units
schools_250_units
schools_450_units
在尋找靠近單位/學校的商店方面,就像在您的其他問題中一樣,您可能會考慮單位的分布范圍 - 當 450 m 緩沖區鏈接在一起時。 以下面的地圖為例。
tm_shape(schools_450_units, bbox = schools_450_units %>% filter(unit == 19) %>% st_buffer(2000) %>% st_bbox)+
tm_polygons(col = 'unit', border.col = 'blue', legend.show = FALSE)+
tm_shape(schools_250_units)+
tm_polygons(col = 'unit', border.col = 'red', legend.show = FALSE)+
tm_shape(schools_units)+
tm_text(text = 'unit')
看看第 3 單元 - 它相當大,幾乎吞沒了第 22 單元。由您決定要做什么以及這是否合適,但這是我基於快速地圖的初步想法之一。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.