Закріплення осиротілих дірок у R


18

Я намагаюся виконати об'єднання на загальному полі після об'єднання двох суміжних фігур. Файли форми закінчуються принаймні одним тонким пробілом між ними. Коли я намагаюся об'єднати, я отримую таку помилку, осиротілу дірку:

Помилка в створенніPolygonsComment (p): rgeos_PolyCreateComment: осиротіла дірка, не вдається знайти багатокутник для отвору в індексі 17

Я завантажив відтворюваний приклад у Dropbox за цим посиланням .

Ось код для відновлення проблеми:

#loading required packages
require(sp)    
require(rgdal)
require(maptools)
require(rgeos)

#load example data, set "dsn=" to your working directory or specify the path
example <- readOGR(dsn=".",layer="ReproducibleExample")

#Attempting a UnionSpatialPolygons based on the COUNTY field
example.df <- as(example, "data.frame")
countycol <- example.df$COUNTY
example.diss <- unionSpatialPolygons(example, countycol)

Повернення:

Помилка в створенніPolygonsComment (p): rgeos_PolyCreateComment: осиротіла дірка, не вдається знайти багатокутник для отвору в індексі 17

Спробуйте виправити запропоновані тут і тут :

slot(example, "polygons") <- lapply(slot(example, "polygons"), checkPolygonsHoles)

Це повертає ту саму помилку, що й при спробі об'єднання, але з іншим номером індексу:

rgeos_PolyCreateComment: осиротіла діра, не вдається знайти багатокутник для отвору в індексі 30

Спробуйте виправити запропоновані у корисному підручнику Роджера Біванда

fix <- slot(example, "polygons")
fixa <- lapply(fix, checkPolygonsHoles)

Повертає ту саму помилку в індексі 30, як вище.

Інші поставили цю проблему тут і тут , і хоча рішення, викладені вище, здаються, працюють у деяких випадках, інші випадки не вирішуються. Один користувач використовував QGIS для вирішення проблеми, а для іншого було виправлено 2 з 3 пункту, але жодного рішення для остаточного не було.

Здається, що люди продовжують мати проблеми, незважаючи на те, що цей код час від часу працює. Хтось знайшов рішення в межах R?

Я виконував інструмент "ремонту геометрії" в ArcGIS, і він виправляв проблему, але, схоже, має бути виправлення в Р.


Без ваших даних важко сказати, де проблема.

@Pascal, я щойно завантажив посилання на випускну скриньку зі зменшеним форматним файлом на 10 Мб і 16 раза розпаковане, що відтворить проблему. Я не знав, як надати дані, оскільки оригінал був 1,5 гбіт, але мені вдалося використовувати ArcGIS, щоб звузити проблему до меншого файлу. Чи є хороший протокол для створення та спільного використання відтворюваних прикладів керованого розміру?
Люк Маколей

Спробувати різні підходи з R не вийшло. І Qgis замерзає при перевірці геометрії.

Відповіді:


25

Я проаналізував питання геометрії у доданих даних, і, здається, це НЕ ТОЛЬКО є, orphaned holesале також geometry validity issues. Це правда, що an orphaned holeякось є питанням дійсності геометрії, але rgeos не вирішує це так само, як і для осиротілих дірок, замість простого попередження виникає помилка. Як ви вказуєте, вони є підказками для перевірки отворів на полігонах, але це не завжди вдало, коли застосовується для того, щоб виправити осиротілі отвори.

Отже, давайте:

  1. очистити свої дані (що потрібно, якщо ви хочете робити геопроцесори на зразок об'єднання)

  2. використовуйте очищені дані під час свого об'єднання

1. Очищення геометрії Виправлення геометрії в R може бути часом складним, тому я спробував створити експериментальний пакет R (див. Https://github.com/eblondel/cleangeo ), який має намір полегшити очищення spоб'єктів (наразі обмежено на багатокутні форми). Ви можете встановити пакет за допомогою:

require(devtools)
install_github("eblondel/cleangeo")
require(cleangeo)

Для початку добре, що ви бачите, які геометричні проблеми у вихідних даних. Для цього ви можете виконати наступне (ваші дані великі, тому це може зайняти деякий час):

#get a report of geometry validity & issues for a sp spatial object
report <- clgeo_CollectionReport(sp)
summary <- clgeo_SummaryReport(report)
issues <- report[report$valid == FALSE,]

З цим ви побачите, що у ваших даних є два типи питань: orphaned holesі geometry validity issues. Обидві (і не тільки осиротілі отвори), ймовірно, можуть зробити unionпроцес невдалим, тому дані слід очищати раніше, коли це можливо, автоматизованим способом. Для швидкого відтворення перший зразок коду нижче містить лише підмножину функцій, позначених як підозрілі (крім останньої, з індексом = 9002 у вихідних даних - див. Мою примітку нижче щодо цього)

#get suspicious features (indexes)
nv <- clgeo_SuspiciousFeatures(report)
mysp <- sp[nv[-14],]

#try to clean data
mysp.clean <- clgeo_Clean(mysp, print.log = TRUE)

#check if they are still errors
report.clean <- clgeo_CollectionReport(mysp.clean)
summary.clean <- clgeo_SummaryReport(report.clean)

Якщо clgeo_Cleanце добре працює, ви повинні отримати всі геометричні чинності зараз. Ви можете застосувати це до повного набору даних (крім індексу функції = 9002)

#try to clean data
mysp <- sp[-9002,]
mysp.clean <- clgeo_Clean(mysp, print.log = TRUE)

#check if they are still errors
report.clean <- clgeo_CollectionReport(mysp.clean)
summary.clean <- clgeo_SummaryReport(report.clean)

2. Процес з'єднання Тепер, давайте подивимося, чи unionпрацює на цьому наборі даних:

#Attempting a UnionSpatialPolygons based on the COUNTY field
mysp.df <- as(mysp, "data.frame")
countycol <- mysp.df$COUNTY
mysp.diss <- unionSpatialPolygons(mysp.clean, countycol)

Примітка: як було сказано раніше, я видаляю одну функцію (індекс = 9002). Побудувавши це: plot(sp[9002,])ви побачите, що ця функція дуже (дуже) складна. Я виключив це із зразка лише тому, що перевірка отворів займала занадто багато часу. Давайте подивимось, якщо така ж проблема виникає при використанні readShapePolymaptools) для читання даних ...

3. Переключіться на readShapePoly проти readOGR для зчитування даних (ОНОВЛЕННЯ)

readOGRне єдина функція, доступна для читання файлів форм. Ви також можете використовувати readShapePolyз maptoolsпакета, як правило, більш ефективний, ніж перший:

require(maptools)
mysp <- readShapePoly("ReproducibleExample.shp")

Крім бігу швидше:

  • якщо ви використовуєте вищезазначений код на основі clgeo_CollectionReport, немає проблеми осиротілих дірок, але все ж проблеми геометрії.

  • Прибирання геометрії clgeo_Cleanтакож працює добре, і тепер вона не зациклюється на індексі 9002

  • І ... процес союзу працює.

Дивіться нижче результат сюжету:

#plot the result
plot(mysp, border= "lightgray")
plot(mysp.diss, border="red", add = TRUE)

Результат союзу

Висновок : краще maptools читати дані шейп файлу, і розглянути можливість використання cleangeo для очищення даних перед будь-яким геообробки.


Дякую Еблондел! Я спробую це. Дякуємо за розробку пакету!
Люк Маколей

Привіт, Еблондель, Це спрацювало добре, але я хотів повідомити вам, що, виправляючи геометрію, часто створюється дуже великий багатокутник при роботі із заплутаними та складними ознаками. Наприклад, дорожня мережа була виправлена ​​на великий багатокутник, який в основному був мірою мережі. Я не впевнений, наскільки легко це виправити, але хотів повідомити про це.
Люк Макалей

Ого. Дуже вражаючий пакет. То, мабуть, було багато роботи.
nograpes

3
Дякуємо @nograpes за ваш відгук. Я будував цей пакет з нуля, коли ця публікація була розміщена ще й тому, що очищення геометрій - це не завжди легке завдання. Якщо ви перебуваєте в Github, я б вітав вашу «зірку» :-), я хотів би в подальшому вдосконалити пакунок і, можливо, випустити його на CRAN.
eblondel

7
Просто, щоб повідомити, що cleangeo було опубліковано в CRAN ( cran.r-project.org/package=cleangeo ), щоб усі користувачі, які його використовують, не соромтеся повідомляти про запити на покращення або помилки в Github.
eblondel

1

Зручне рішення, яке продовжує працювати для мене в R, - застосувати буфер нульової ширини :

#loading required packages
require(sp)    
require(rgdal)
require(maptools)
require(rgeos)

#load example data, set "dsn=" to your working directory or specify the path
example <- readOGR(dsn=".",layer="ReproducibleExample")

#project your data (I'm using California Albers here) and apply a zero-width buffer
example <- spTransform(example, CRS("+init=epsg:3310"))
example <- gBuffer(example, byid = T, width = 0)

#Attempting a UnionSpatialPolygons based on the COUNTY field
example.df <- as(example, "data.frame")
countycol <- example.df$COUNTY
example.diss <- unionSpatialPolygons(example, countycol)

unionSpatialPolygons займає деякий час з цим набором даних, але, здається, працює чудово.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.