保留完全或部分在一个更大的多边形内的多边形,没有负缓冲区

Keep polygons that are fully or partially within a larger one without a negative buffer

我想保留构成更大人口普查地理区域的人口普查区域。这些区域应该完全适合更大的地理范围。

我可以使用负缓冲区来做到这一点,但是有更好的方法吗?

library(tidyverse)
library(sf)
library(tidycensus)
library(tigris)
library(tmap)

balt <- places("Maryland",
               year = 2018,
               class = "sf") %>% 
  filter(NAME == "Baltimore") %>% 
  st_transform(4326)

balt_tracts <- get_acs(geography = "tract",
                       variables = "B01003_001E", # population
                       year = 2018,
                       state = "Maryland",
                       survey = "acs5",
                       geometry = TRUE) %>% 
  st_transform(4326)

balt_tracts %>% 
  .[st_within(st_buffer(., -0.001),  
              balt) %>% lengths > 0,] %>% 
  qtm()

一个交叉点 returns 在共享边缘的较大地理区域之外,我不想要这样。

balt_tracts[balt,] %>% 
  qtm()

编辑

我正在寻找一种方法来获取 st_overlaps() 的结果并仅保留边界内的那些多边形 (balt)。

balt_tracts[st_overlaps(balt_tracts, balt) %>% lengths > 0,] %>% 
  tm_shape() + tm_polygons(col = "GEOID")

我注意到的一件事是 st_touches() returns 只有三个多边形。这是一个精度问题,还是意味着人口普查区边界实际上并未与较大多边形的边界完全对齐?

 balt_tracts[st_touches(balt_tracts, balt) %>% lengths > 0,] %>% 
   tm_shape() + tm_polygons(col = "GEOID")

一种替代方法是将每个区域变成一个点并在这些区域上相交,这样可以消除给我带来麻烦的重合边界。这种方法不需要像第一个问题中那样选择任意缓冲距离。

st_point_on_surface() 优于 st_centroid(),因为它保证点位于多边形的表面上,而一些多边形的质心位于其表面之外。

balt_tracts[st_point_on_surface(balt_tracts)[balt,],] %>% 
  qtm()

在您的具体示例中,您应该只向 get_acs() 提供一个 county 参数,因为巴尔的摩市是一个独立的实体:

library(tidyverse)
library(sf)
library(tidycensus)
library(tigris)
library(tmap)

balt_tracts <- get_acs(geography = "tract",
                       variables = "B01003_001E", # population
                       year = 2018,
                       state = "Maryland",
                       county = "Baltimore city",
                       survey = "acs5",
                       geometry = TRUE) 

qtm(balt_tracts)

不过,你提出的更广泛的问题是一个值得提出的问题。如果您知道您的几何形状完全对齐(就像在同一年使用 tigris/tidycensus 时一样,前提是 cb = TRUEcb = FALSE 始终如一地使用),您可以使用 sf::st_filter()st_within 空间谓词来进行空间子集化。例如,假设我们想要获取巴尔的摩 都会区 (完全位于马里兰州)的人口普查区:

balt_metro <- core_based_statistical_areas(cb = TRUE, 
                                           year = 2018, 
                                           class = "sf") %>%
  filter(str_detect(NAME, "Baltimore"))

balt_metro_tracts <- tracts("MD", cb = TRUE, 
                            year = 2018, class = "sf") %>%
  st_filter(balt_metro, .predicate = st_within)

ggplot() + 
  geom_sf(data = balt_metro_tracts, fill = "white") + 
  geom_sf(data = balt_metro, fill = NA, color = "red")