Извлечение родительского многоугольника из вложенного SpatialPolygonsDataFrame или "растворения" отверстий из родительского плойгона

РЕДАКТИРОВАТЬ После дополнительных исследований и до сих пор нет решения, я добавляю существенное редактирование, а также ссылку на файл.shp.

Файл формы включен здесь

У меня есть SpatialPolygonsDataFrame, который содержит 9 многоугольников, каждый из которых также содержит несколько вложенных многоугольников - "дыр". Сводка данных здесь.

> summary(data)
Object of class SpatialPolygonsDataFrame
Coordinates:
        min       max
x  483298.9  643204.4
y 4782172.1 4997248.3
Is projected: TRUE 
proj4string :
[+proj=utm +zone=12 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0]
Data attributes:
       Id          IndID  
 Min.   :0   BHS_011_A:1  
 1st Qu.:0   BHS_015_A:1  
 Median :0   BHS_083_A:1  
 Mean   :0   BHS_089_A:1  
 3rd Qu.:0   BHS_091_A:1  
 Max.   :0   BHS_129_A:1  
             (Other)  :3  

Образец structure данных ниже.

Formal class 'SpatialPolygonsDataFrame' [package "sp"] with 5 slots
  ..@ data       :'data.frame': 9 obs. of  2 variables:
  .. ..$ Id   : int [1:9] 0 0 0 0 0 0 0 0 0
  .. ..$ IndID: Factor w/ 9 levels "BHS_011_A","BHS_015_A",..: 1 2 3 4 5 6 7 8 9
  ..@ polygons   :List of 9
  .. ..$ :Formal class 'Polygons' [package "sp"] with 5 slots
  .. .. .. ..@ Polygons :List of 5
  .. .. .. .. ..$ :Formal class 'Polygon' [package "sp"] with 5 slots
  .. .. .. .. .. .. ..@ labpt  : num [1:2] 513497 4986246
  .. .. .. .. .. .. ..@ area   : num 76614017
  .. .. .. .. .. .. ..@ hole   : logi FALSE
  .. .. .. .. .. .. ..@ ringDir: int 1
  .. .. .. .. .. .. ..@ coords : num [1:287, 1:2] 509244 507384 507214 507010 506899 ...
  .. .. .. .. .. .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. .. .. .. .. .. ..$ : NULL
  .. .. .. .. .. .. .. .. ..$ : chr [1:2] "x" "y"
  .. .. .. .. ..$ :Formal class 'Polygon' [package "sp"] with 5 slots
  .. .. .. .. .. .. ..@ labpt  : num [1:2] 509678 4979511
  .. .. .. .. .. .. ..@ area   : num 1462398
  .. .. .. .. .. .. ..@ hole   : logi TRUE
  .. .. .. .. .. .. ..@ ringDir: int -1
  .. .. .. .. .. .. ..@ coords : num [1:7, 1:2] 509301 509269 509194 509007 509412 ...
  .. .. .. .. .. .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. .. .. .. .. .. ..$ : NULL
  .. .. .. .. .. .. .. .. ..$ : chr [1:2] "x" "y"
  .. .. .. .. ..$ :Formal class 'Polygon' [package "sp"] with 5 slots
  .. .. .. .. .. .. ..@ labpt  : num [1:2] 515572 4988493
  .. .. .. .. .. .. ..@ area   : num 1579348
  .. .. .. .. .. .. ..@ hole   : logi TRUE
  .. .. .. .. .. .. ..@ ringDir: int -1
  .. .. .. .. .. .. ..@ coords : num [1:10, 1:2] 514520 514570 514684 516501 515996 ...
  .. .. .. .. .. .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. .. .. .. .. .. ..$ : NULL
  .. .. .. .. .. .. .. .. ..$ : chr [1:2] "x" "y"

Как видно из приведенного ниже примера (одного из девяти), родительский полигон имеет несколько отверстий.

data <- readOGR(".", "IndLineBuff")
plot(data[data$IndID == "MTG_005_A",])

Это мой первый набег в sp(), rgdal(), rgeos()и другие пространственные пакеты, и я нашел несколько полезных постов, касающихся использования операторов для извлечения области и т. д., но, тем не менее, остаются вопросы. Хотя этот пост предлагает решения, которые близки, я не могу адаптировать код для удовлетворения потребностей, описанных здесь.

Я хочу получить SpatialPolygonsDataFrame, который содержит только родительский (самый большой) полигон из каждого набора подсписков (то есть data@polygon). Кажется, я должен быть в состоянии либо извлечь только родительский полигон, либо "растворить" дыры.

Конечный результат будет 9 полигонов, каждый из которых является родителем 9 списков, которые я мог бы экспортировать как шейп-файл ESRI.

Мы ценим любые предложения.

2 ответа

Решение

Следующий хак может сработать:

data@polygons = lapply(data@polygons, function(x) { x@Polygons = x@Polygons[1]; x})
plot(data[data$IndID == "MTG_005_A",])

В вашем случае кажется, что вы буферизировали линейные объекты или около того, и хотите избавиться от дыр в полигонах. Кажется, что каждый из 9 многоугольников состоит из основного многоугольника, за которым следует набор целых. Функция выбирает первый из этого списка, возвращая требуемый список списков. Чтобы понять структуру класса, изучите ?"SpatialPolygons-class", ?"Polygons-class" а также ?"Polygon-class" внимательно.

Когда я впервые узнал о sp и связанных пакетах, я нашел сайт Барри Роулингсона очень полезным.

Это включает:

  • Шпаргалка
    Действительно полезный справочный лист с советами о том, как сделать что-то с помощью пакетов R \ http://www.maths.lancs.ac.uk/~rowlings/Teaching/UseR2012/cheatsheet.html

  • Введение в Пространство
    Объяснение структур пространственных данных, созданных пакетом sp. Также объясняются CRS (системы координат координат) и проекции (proj4string и proj4.Project). Наконец, также рассматриваются использование растровых изображений и манипулирование ими, а также извлечение данных из них с помощью R \ http://www.maths.lancs.ac.uk/~rowlings/Teaching/UseR2012/static/talk1.pdf

Возвращаясь к вашему вопросу, это грязно, потому что вы имеете дело со списками списков вещей, но это можно сделать.

Следующий код, кажется, работает (я уже проверил его (немного) на шейп-файле, который я уже использовал, а не скачал ваш). Если вы замените NSWACTA с именем вашего шейп-файла после того, как вы его прочитали, он должен работать для вашего случая. Никаких обещаний, хотя:-).

Первая часть является вводной, чтобы показать, что происходит со всеми списками списков классов. Надеюсь, это поможет вам понять, что происходит. Это dropHole функция и ее методы, которые на самом деле делают то, что вы хотите.

class(NSWACTA)
# NSWACTA has class sp::SpatialPolygonsDataFrame
slotNames(NSWACTA)
# The SpatialPolygonsDataFrame has a slot called @polygons
class(NSWACTA@polygons)
# The @polgyons slot contains a list
class(NSWACTA@polygons[[1]])
# Elements of that list are of class sp::Polygons 
slotNames(NSWACTA@polygons[[1]])
# An sp::Polygons class has several slots, one of which is @Polygons
class(NSWACTA@polygons[[1]]@Polygons)
# The @Polygons slot contains a list
class(NSWACTA@polygons[[1]]@Polygons[[1]])
# The entries in the @Polygons list are of class sp::Polygon
slotNames(NSWACTA@polygons[[1]]@Polygons[[1]])
# An sp::Polygon has several slots. 
# @coords holds the coordinates which define the boundary.
# @hole is a logical field indicating whether or not the sp::Polygon is a hole 

setGeneric('dropHole',def=function(poly, ...){
  standardGeneric('dropHole')
})

# Drop a single sp::Polygon if it is holey
setMethod('dropHole',signature=signature('Polygon'),
          def=function(poly) {
            #return only Polygons which are not holes
            if (poly@hole) NULL else poly
          }
          )

# Drop holey sp::Polygon entries in the @Polygons list of an sp::Polygons class
setMethod('dropHole', signature = signature('Polygons'),
          def = function(poly) {
            noHoles <- lapply(poly@Polygons, dropHole)
            #Remove the NULL entries from the list
            noHoles <- Filter(Negate(is.null), noHoles)
            # Turn back into a (single) Polygons
            # The generator function (sp::Polygons) fills in the other slots!
            # return the new sp:Polygons object
            sp::Polygons(noHoles, ID = poly@ID)
          }
          )

# Drop holey parts of sp::Polygons in the @polygons list 
# of an sp::SpatialPolygonsDataFrame
setMethod('dropHole', signature = signature('SpatialPolygonsDataFrame'),
          def = function(poly) {
            noHoles <- lapply(poly@polygons, dropHole)
            # Put the un holey Polygons list back into the @polygons slot 
            poly@polygons <- noHoles
            #return the modified SpatialPolygonsDataFrame 
            poly
          }
          )

newmap <- dropHole(NSWACTA)

Вот вывод из первой части. Обратите внимание на различия между прописными и строчными буквами в именах, а также между единственным и множественным числами! (т.е. полигоны, полигоны и полигоны)

d> class(NSWACTA)
[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"
d> # NSWACTA has class sp::SpatialPolygonsDataFrame
d> slotNames(NSWACTA)
[1] "data"        "polygons"    "plotOrder"   "bbox"        "proj4string"
d> # The SpatialPolygonsDataFrame has a slot called @polygons
d> class(NSWACTA@polygons)
[1] "list"
d> # The @polgyons slot contains a list
d> class(NSWACTA@polygons[[1]])
[1] "Polygons"
attr(,"package")
[1] "sp"
d> # Elements of that list are of class sp::Polygons 
d> slotNames(NSWACTA@polygons[[1]])
[1] "Polygons"  "plotOrder" "labpt"     "ID"        "area"     
d> # An sp::Polygons class has several slots, one of which is @Polygons
d> class(NSWACTA@polygons[[1]]@Polygons)
[1] "list"
d> # The @Polygons slot contains a list
d> class(NSWACTA@polygons[[1]]@Polygons[[1]])
[1] "Polygon"
attr(,"package")
[1] "sp"
d> # The entries in the @Polygons list are of class sp::Polygon
d> slotNames(NSWACTA@polygons[[1]]@Polygons[[1]])
[1] "labpt"   "area"    "hole"    "ringDir" "coords" 
d> # An sp::Polygon has several slots. 
d> # @coords holds the coordinates which define the boundary.
d> # @hole is a logical field indicating whether or not the sp::Polygon is a hole
Другие вопросы по тегам