Получение значения слота объектов S4?

Итак, у меня есть объект пространственных полигонов в R; но я не уверен, почему я не могу извлечь из него слот «область».

Вот мой сеанс R:

> spatialpolygons
An object of class "SpatialPolygons"
Slot "polygons":
[[1]]
An object of class "Polygons"
Slot "Polygons":
[[1]]
An object of class "Polygon"
Slot "labpt":
[1] 20.50516 57.72918

Slot "area":
[1] 36.85484

Slot "hole":
[1] FALSE

Slot "ringDir":
[1] 1

Slot "coords":
         [,1]     [,2]
[1,] 16.48438 59.73633
[2,] 22.59277 61.14258
[3,] 24.74609 55.03418
[4,] 17.49512 55.12207
[5,] 16.48438 59.73633



Slot "plotOrder":
[1] 1

Slot "labpt":
[1] 20.50516 57.72918

Slot "ID":
[1] "myMultiPolygons"

Slot "area":
[1] 36.85484



Slot "plotOrder":
[1] 1

Slot "bbox":
       min      max
x 16.48438 24.74609
y 55.03418 61.14258

Slot "proj4string":
CRS arguments:
 +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 

> spatialpolygons@bbox
       min      max
x 16.48438 24.74609
y 55.03418 61.14258
> spatialpolygons@area
Error: no slot of name "area" for this object of class "SpatialPolygons"
> slotNames(spatialpolygons)
[1] "polygons"    "plotOrder"   "bbox"        "proj4string"
> names(spatialpolygons)
[1] "myMultiPolygons"

person Calvin Cheng    schedule 03.01.2012    source источник


Ответы (2)


Во-первых, вы должны знать, что слот @area не является надежным источником информации о реальной площади объекта SpatialPolygons*. Как отмечено в ?"Polygons-class", слот @area используется просто как дополнение к построению (предотвращает закрашивание меньших полигонов большими) и не учитывает проекцию или должным образом не учитывает отверстия в полигонах.

Чтобы получить точные площади, вы должны вместо этого использовать rgeos::gArea() для слоев с проекционными системами координат или geosphere::areaPolygon() для тех, которые находятся в системах координат широта-долгота (т. е. CRS(+proj=longlat)).

С учетом этих предостережений ниже показано, как вы можете получить содержимое слотов @area, если вы действительно этого хотите.


Основная сложность заключается в том, что слот области принадлежит объекту Polygon, а не объекту SpatialPolygons (одним из элементов которого является объект Polygon). . Таким образом, вам нужно сначала углубиться в объект SpatialPolygons, чтобы извлечь его в отдельные объекты Polygon.

После того, как вы это сделали, вы можете просто использовать оператор @ для извлечения содержимого слота области.

В следующем примере используется объект SpatialPolygons, созданный в разделе 7 документа sp виньетка пакета (предупреждение, pdf):

require(sp)
# Example pasted in from Section 7 of the sp vignette
Sr1 = Polygon(cbind(c(2,4,4,1,2),c(2,3,5,4,2)))
Sr2 = Polygon(cbind(c(5,4,2,5),c(2,3,2,2)))
Sr3 = Polygon(cbind(c(4,4,5,10,4),c(5,3,2,5,5)))
Sr4 = Polygon(cbind(c(5,6,6,5,5),c(4,4,3,3,4)), hole = TRUE)
Srs1 = Polygons(list(Sr1), "s1")
Srs2 = Polygons(list(Sr2), "s2")
Srs3 = Polygons(list(Sr3, Sr4), "s3/4")
SpP = SpatialPolygons(list(Srs1,Srs2,Srs3), 1:3)

# To extract the area of the first (or in your case only) Polygon
SpP@polygons[[1]]@area
# [1] 5.5

# Extract the areas of all three component Polygons
sapply(SpP@polygons, function(x) x@area)
# [1]  5.5  1.5 10.0

## For areas, rgeos::gArea() or geosphere::areaPolygons() are generally more appropriate
## (Note, for instance, that it properly accounts for the hole in the 3rd polygon.)
rgeos::gArea(SpP, byid=TRUE)
#  s1   s2 s3/4 
# 5.5  1.5  9.0 
person Josh O'Brien    schedule 03.01.2012
comment
поэтому для моего случая, когда есть только 1 полигон, работает spatialpolygons@polygons[[1]]@area. - person Calvin Cheng; 03.01.2012
comment
Точно, и рад, что это сработало для вас. Я добавлю это к ответу для полноты. - person Josh O'Brien; 03.01.2012
comment
Просто для удовольствия, это также сработает: slot(slot(Sp, "polygons")[[1]], "area"). :) Вы также можете проверить имена слотов с помощью slotNames. - person Roman Luštrik; 04.01.2012
comment
@JoshO'Brien ?sapply заявляет, что: Пользователи классов S4 должны передавать список в lapply и vapply ... Лучше использовать lapply или vapply. - person imanuelcostigan; 15.01.2013
comment
@imanuelc - Интересный улов, но я думаю, что вы неправильно это анализируете. По крайней мере, я читал, что если вы используете классы S4 с lapply или vapply, лучше всего передать их в виде списка (поскольку обе эти функции вызывают as.list(), что может изменить ваш объект неожиданным образом) . (sapply не звонит as.list(), поэтому такого предупреждения нет.) - person Josh O'Brien; 15.01.2013
comment
+1. А как насчет слота «координаты»? Я не мог получить их, хотя. - person Andre Silva; 07.10.2014
comment
@AndreSilva - Координаты находятся еще на один уровень ниже в структуре, поэтому вам нужно сделать что-то вроде sapply(SpP@polygons, function(x) coordinates(x@Polygons[[1]])). (Эти объекты sp, несмотря на то, что в некоторых аспектах они хорошо спроектированы, оказываются не очень удобными для пользователя, по крайней мере, когда вы только начинаете с ними работать!) - person Josh O'Brien; 07.10.2014

Вы можете вычислить площадь с помощью функций в пакете rgeos, примеры ниже, используя данные примера Джоша. Это может быть более подходящим, поскольку слот area предназначен только для построения графиков.

library(rgeos)
gArea(SpP[1,])
## [1] 5.5
gArea(SpP[2,])
##[1] 1.5
gArea(SpP[3,])
## [1] 10

Все сразу:

gArea(SpP)
[1] 17

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

На страницах справки обсуждается слот area.

?gArea
....

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

?"Polygons-class"
...

«площадь»: объект класса «числовой»; общая плоская площадь списка полигонов, но без двойного подсчета отверстий (изменено с 0,9 до 58 - острова суммируются, отверстия игнорируются, а не вычитаются); эти значения используются для того, чтобы полигоны меньшей площади отображались после полигонов большей площади, не учитывают проекцию, поскольку объекты этого класса не имеют определенной проекции

person mdsumner    schedule 03.01.2012
comment
@mdsummer: отличный совет. СПАСИБО! - person Calvin Cheng; 03.01.2012