#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. В случае с ребрами я имел в виду некоторые примеры геометрии, которые не будут работать при таком подходе или которые могут указывать на другую проблему.