Проверка того, включают ли геометрии другие при касании границ в R

#r #maps #gis #polygon #sf

Вопрос:

Я новичок в геоданных, так что, возможно, это глупый вопрос. У меня есть два мультиполигона, и я хочу проверить, в каком из многоугольников «округов» содержится каждый многоугольник «подопечных». В основном, чтобы увидеть для каждого прихода, в каком состоянии он находится.

Однако у меня возникли проблемы с функцией st_within() from sf , потому что она возвращает значение TRUE только в том случае, если первая геометрия полностью соответствует второй геометрии. Это проблема, когда меньшие единицы касаются границ более крупных. Вот пример

У меня есть один мультиполигон под названием «конъюнкции» и один под названием «подопечные». Вы можете найти их здесь: https://www.dropbox.com/sh/xu08wm79rym00zz/AADFDpyPe0EuDSDSY-6SvqpYa?dl=0

В округах есть 2 объекта:

 plot(constituencies$geometry)
 

введите описание изображения здесь
Затем я пытаюсь присоединиться к ним в вопросе о том, находятся ли подопечные в пределах избирательных округов

 wards <- st_transform(wards, crs = st_crs(constituencies))
test98 <- st_join(wards, constituencies, join=st_within)
 

И результат выплевывает много NAs на название избирательных округов и ярлык, в пределах которого находится округ.

     head(test98)
Simple feature collection with 6 features and 4 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: 531936.6 ymin: 180569.5 xmax: 533595.1 ymax: 182082.5
projected CRS:  OSGB 1936 / British National Grid
  WD98CD       WD98NM                             name label                       geometry
1 00AAFA   Aldersgate                             <NA>  <NA> MULTIPOLYGON (((532104.9 18...
2 00AAFB      Aldgate                             <NA>  <NA> MULTIPOLYGON (((533319.2 18...
3 00AAFC    Bassishaw Cities of London and Westminster   107 MULTIPOLYGON (((532587.3 18...
4 00AAFD Billingsgate Cities of London and Westminster   107 MULTIPOLYGON (((533167.9 18...
5 00AAFE  Bishopsgate                             <NA>  <NA> MULTIPOLYGON (((533410.7 18...
6 00AAFF Bread Street Cities of London and Westminster   107 MULTIPOLYGON (((532300.3 18...
 

Когда я строю их, чтобы увидеть, какие из них имеют NA в названии (красным цветом), вы можете видеть, что это те, которые касаются границ согласия:

 plot(constituencies_short$geometry)
plot(test98$geometry[!is.na(test98$name),], col = "green", add = T)
plot(test98$geometry[is.na(test98$name),], col = "red", add = T)
 

введите описание изображения здесь

Я предполагаю, что происходит одна из двух вещей: 1) прикосновение к границам не считается полностью вписывающимся в геометрию, или 2) границы отделений и округов могут быть не совсем совпадающими, поэтому отделения не полностью находятся в пределах округа.

Мой вопрос заключается в следующем: есть ли способ идеально сопоставить границы, а затем проверить, какие приходы находятся в пределах каких округов, или есть способ проверить, в каких округах находятся не все, а большинство границ прихода?

Большое вам спасибо!

Комментарии:

1. Привет, отличный вопрос! К сожалению, я не могу открыть ваши наборы данных. Мне бросается в глаза одна строка вашего кода: st_crs(wards) == st_crs(constituencies) обычно это плохая идея, потому что она просто перезаписывает CRS. Попробуй st_transform(wards, st_crs(constituencies) вместо этого!

2. Ах, большое вам спасибо! Исправлю это. Стыдно за ссылку, не могу понять, почему это так. Не могли бы вы вместо этого попробовать вот это: drive.google.com/drive/folders/… ?

3. Я могу загрузить их, но здесь, похоже, CRS одинаковы (но геометрия немного не та). Вы уже манипулировали CRS здесь? Также я ошибся в своем предыдущем комментарии: ваша строка кода не изменяет CRS, она просто проверяет, равны ли они. Это выражение TRUE для меня, использующего ваши данные.

4. Извини, ты прав. Я управлял «подопечными Я соответствующим образом отредактирую свой вопрос

5. Можете ли вы предоставить образцы неизмененных наборов данных? Кроме того, любая информация о том, откуда они пришли (какие CRS использовались), была бы полезна, чтобы попытаться правильно их выровнять.

Ответ №1:

Ваши границы не совпадают точно. Давайте посмотрим, что произойдет, когда мы пересечем первый округ с двумя округами:

 > st_intersection(wards$geom[1], constituencies$geom)
Geometry set for 2 features 
geometry type:  GEOMETRY
dimension:      XY
bbox:           xmin: 531936.6 ymin: 181262.6 xmax: 532309 ymax: 182012
projected CRS:  OSGB 1936 / British National Grid
POLYGON ((532104.9 182011.9, 532126.3 181948, 5...
MULTIPOLYGON (((532022.4 181893.5, 532022.4 181...
 

мы получаем две функции вывода, потому что у прихода есть некоторые из них в обоих округах. Сколько? Давайте посмотрим:

 > st_area(st_intersection(wards$geom[1], constituencies$geom))
Units: [m^2]
[1] 1.298829e 05 9.542473e-01
 

Таким образом, это 129882 м^2 в одном и 0,95 м^2 в другом. Ваши границы смещены так, что 1 квадратный метр участка находится в «неправильном» избирательном округе!

Исправлением было бы вычисление площадей полного набора пересечений и порогового значения или доли площади отделения.

Вы можете использовать st_intersects , чтобы получить список всех перекрытий:

 > st_intersects(wards, constituencies)

Sparse geometry binary predicate list of length 25, where the predicate was `intersects'
first 10 elements:
 1: 1, 2
 2: 1
 3: 1
 4: 1
 5: 1, 2
 6: 1
 

Любые элементы этого списка с одним элементом являются отделениями, которые перекрывают один и только один округ, в противном случае вам необходимо вычислить пропорции площади перекрытия этого прихода с этими округами, чтобы определить, какие из них в основном закончены.

Комментарии:

1. Спасибо, это действительно полезно! Однако я возвращаюсь к тому же вопросу, верно? Использование sf_intersects дает мне каждое пересечение, а не избирательный округ, в котором находится большая часть геометрии прихода. Не могли бы вы просто предоставить пример кода того, как мне «нужно будет вычислить пропорции площади перекрытия этого прихода с этими округами, чтобы определить, какие из них в основном закончены»? Большое вам спасибо!

2. Извините, иногда у меня нет времени писать полные решения, и я оставил его в месте, где кто-то, кто немного разбирается в программировании на R, должен был закончить работу. i Просмотрите выходные st_intersects данные , вычислите st_area округ i и округа в i-th элементе списка пересечений, примите решение о том, что предпринять.

3. справедливо, мне очень жаль! Я все еще довольно новичок во всем этом и не хотел задавать никаких неуместных вопросов. Это было просто для того, чтобы убедиться, что я понял, и получить полный ответ здесь для других в будущем. Спасибо!

Ответ №2:

Поскольку мы имеем дело только с небольшими различиями, одним из подходов было бы создать небольшой буфер отрицания / вставки вокруг геометрии подопечных перед присоединением.

Подготовка

 library(sf)
library(tmap)

wards_transformed <- st_transform(wards, st_crs(constituencies))
 

Без буфера:

 wards_transformed %>%
  st_join(constituencies, st_within)
 

Результат (без буфера)

С отрицательным буфером:

 wards_transformed %>%
  st_buffer(-10) %>%
  st_join(constituencies, st_within)
 

введите описание изображения здесь

Комментарии:

1. Отлично, большое вам спасибо! Это делает трюк в примере, который я привел здесь, но в полном наборе данных я все еще получаю много NAs, вероятно, потому, что различия там могут быть в некотором роде больше или потому, что может возникнуть другая проблема.

2. Если вы хотите поделиться некоторыми примерами, я был бы рад взглянуть!

3. Действительно? Большое вам спасибо! Это очень мило с твоей стороны. Вы можете найти два полных набора данных здесь: drive.google.com/drive/folders/…

4. В случае с ребрами я имел в виду некоторые примеры геометрии, которые не будут работать при таком подходе или которые могут указывать на другую проблему.