Właściwości i operatory SpatialPointsDataFrame w R

14

Stworzyłem obiekt typu SpatialPointsDataFrameza pomocą sppakietu w R. Jednak jestem zdezorientowany co do @, $, . and []operatorów i kiedy ich używać, aby uzyskać dostęp do różnych właściwości mojego obiektu. Oto mój przykładowy kod:

library(sp)
library(rgdal)

#creating a SpatialPointsDataFrame with sample points in UTM
x <- c(15.2, 15.3, 15.4, 15.5, 15.7)
y <- c(50.4, 50.2, 50.3, 50.1, 50.4)
v1 <- c(1.0, 2.0, 3.0, 4.0, 5.0)
v2 <- c("a","b","b","c","a")
attributes <- as.data.frame(cbind(v1,v2))
xy <- cbind(x,y)
locationsDD <- SpatialPointsDataFrame(xy, attributes)
proj4string(locationsDD) <- CRS("+proj=longlat")
locations <- spTransform(locationsDD, CRS("+proj=utm +zone=33"))
plot(locations)

#using the different operators: WHEN TO USE @, $ or [] ?

#all these work!
property1 <- locations$v1
property2 <- locations@data$v1
property3 <- locations@data[,"v1"]
property4 <- locations@data["v1"]

#these also work
property5 <- locations@coords
property6 <- locations@bbox
property7 <- locations@coords[,2]

#these three work only in my special case
property8 <- locations@coords[,"y"]
property9 <- locations$x
property10 <- locations$y

#these don't work: $ operator is invalid for atomic vectors
property11 <- locations@coords$x
property12 <- locations@coords$y

Czy ktoś może mi pomóc, kiedy korzystać z @, $, []operatorów? Kiedy próbuję przeczytać dokumentację ?SpatialPointsDataFrame, widzę różne właściwości, takie jak coordslub, bboxale jestem zdezorientowany, którego operatora @, $, []użyć, aby uzyskać do nich dostęp lub zmodyfikować.

jirikadlec2
źródło
1
Ponieważ tak naprawdę jest to pytanie dotyczące Rskładni, nie dotyczy ono w szczególności sppakietu ani jego obiektów. Rjest zainstalowany z samouczkiem: zacznij od swoich badań. Internet i media drukowane oferują bogactwo dodatkowych zasobów do nauki R.
whuber

Odpowiedzi:

21

Przestrzenne dane sp są obiektami klasy S4 i składają się ze szczelin (nazywanych za pomocą @), które zawierają komponenty reprezentowanej klasy cech przestrzennych (np. @Data zawiera atrybuty, @coords zawierają pary współrzędnych itp.). Możesz zwrócić nazwy gniazd najwyższego poziomu za pomocą slotNames (), ale nie są one rekurencyjne i nie zwrócą nazw zagnieżdżonych obiektów klasy wieloboków. Każdy slot może zawierać inną klasę obiektów i przed użyciem na nim powinien zostać sprawdzony za pomocą str () lub class (). Szczelina @data jest zawsze obiektem data.frame, a @coords jest matrycą, podczas gdy @polygons to obiekt listy z dodatkowymi szczelinami (labpt, area, hole, ringDir i coords).

Dostępne miejsca i ich organizacja zależy od rodzaju reprezentowanej klasy obiektów. Obiekty SpatialPointsDataFrame są najbardziej podstawowe, podczas gdy obiekty SpatialPolygonsDataFrame mają zagnieżdżanie (jak pokazano powyżej). Ta zagnieżdżona struktura, reprezentująca każdy wielokąt, musi zostać rozliczona z użycia czegoś podobnego do sapply do obsługi każdego obiektu listy (wielokąta).

Oto przykład, który używa sapply do zwrócenia obszaru dla każdego wielokąta poprzez iterację przez „wielokąty”, a następnie zagnieżdżone „obszary” obszaru.

sapply(slot(sdat, 'polygons'), function(i) slot(i, 'area')) 

W przypadku obiektów wielokątów, ponieważ są one przechowywane jako lista dla każdego wielokąta, można alternatywnie użyć indeksowania listy. Oto przykład, aby zwrócić pierwszy wielokąt (w wyniku czego powstaje obiekt klasy „Polygon”, a nie SpatialPolygonsDataFrame):

sdat@polygons[[1]]

W nowszych wersjach SP programiści zaczęli w niektórych przypadkach eliminować konieczność bezpośredniego wywoływania slotu @data.

Na przykład, aby zindeksować @ dane, wcześniej:

sdat@data[sdat@data$att >= 0.5 ,]  

i teraz:

sdat[sdat$att >= 0.5 ,]

Jednak, jak wskazano wcześniej, nie dotyczy to innych szczelin (np. Współrzędnych, wielokątów itp.). Jeśli chodzi o to, kiedy użyć [] lub $, to wciąż zależy od rodzaju operacji. Nawiasów „[]” można używać do wywoływania nazwy w ramce danych, ale są one przede wszystkim używane do indeksowania, natomiast $ służy do wywoływania kolumny w ramce danych. Powodem, dla którego działa „pośrednie” wywołanie nazwy kolumny, jest to, że programiści dodali funkcjonalność, która umożliwia rekurencyjne przeszukiwanie obiektu sp. Jednak, aby uniknąć konfliktów nazw (jak w twoim przykładzie; posiadanie kolumn x, y w ramce danych powodowałoby konflikt z nazwami x, y w nazwach macierzy @coord), istnieje pewna wewnętrzna kontrola spójności, która wyjaśnia, dlaczego działa to tylko w niektórych instancje.

Jedną z dogodnych cech jest to, że można podzestawić obiekt przestrzenny poprzez indeks wiersza. Tutaj dzielę pierwsze 10 obiektów.

sub.sdat <- sdat[1:10,] 

Lub alternatywnie losowa próbka (n = 10) przy użyciu wektora indeksu wiersza.

rs.sdat <- sdat[sample(1:nrow(sdat), 10),]

Zrozumienie indeksowania i używania nawiasów jest bardzo ważną rzeczą przy pisaniu kodu R.

Edycja (24.03.2017): Należy pamiętać, że prosta klasa funkcji (sf), zgodna ze standardem GeoJSON, prawdopodobnie stanie się nowym standardem dla obiektów przestrzennych w R. Szczegółowy opis tej klasy można przeczytać w CRAN sf strona Proste funkcje dla R .

Jeffrey Evans
źródło
Dzięki za szczegółowe wyjaśnienie tego, co dzieje się za kulisami. Wydaje się, że SpatialPointsDataFramenie tylko kolumny @data, ale także kolumny @coords można pobrać z $operatorem bez konieczności wywoływania szczeliny @coords. Więc sdat@coords$eastingdaje taki sam wynik jak sdat$easting.
jirikadlec2
Wygląda na to, że wywołujesz kolumnę w danych <at>. To nie to samo, co gniazdo <at> coords. Zauważysz, że jeśli wywołasz nazwy kolumn (sdat <at> coords), zwrócisz nazwy kolumn macierzy: „coords.x1”, „coords.x2”. Nie jest konieczne utrzymywanie współrzędnych w ramce danych, a ponieważ jest ona powielona, ​​talia pamięci.
Jeffrey Evans
Nie. Nie dzwonię do kolumny w danych <at>. Korzystanie ze SpatialPointsDataFrame z mojego przykładowego skryptu colnames(locations@coords)zwraca, [1] "x" "y"ale colnames(locations@data)zwraca [1] "v1" "v2". Może zachowanie zależy od funkcji użytej do utworzenia SpatialPointsDataFrame?
jirikadlec2
Właściwie mam błąd w moim pierwszym komentarzu. sdat@coords$eastingnie działa, ponieważ sdat @ coords jest matrycą. Ale sdat@coords[,"easting"]jest równoważne sdat@coords[,1]i sdat$easting.
jirikadlec2
Jedno zastrzeżenie, colnames () służy do zwracania nazw kolumn w macierzy, podczas gdy names () zwróci NULL. Chociaż zarówno names (), jak i colnames () będą działać na obiekcie ramki danych, takim jak <at> data. Najlepszym sposobem na odzyskanie danych z macierzy współrzędnych <at> jest ich indeksowanie: sdat <at> coords [, 1] lub według nazwy kolumny sdat <at> coords [, "coords.x1"], ale jak zauważyłeś $ robi nie działa, ponieważ jest to obiekt macierzowy.
Jeffrey Evans
4

Powinieneś spróbować str(locations)to wyjaśnić.

na przykład te są poprawne:

property2 <- locations@data$v1
property5 <- locations@coords
property6 <- locations@bbox
property7 <- locations@coords[,"x"]
property8 <- locations@coords[,2]

I to property1 <- locations$v1działa, ponieważ odwołuje się do data.frame wewnątrz lokalizacji, @data

Guillermo Olmedo
źródło
str(locations)dał mi kilka dobrych wskazówek. Teraz rozumiem, że @jest używany do „slotu klasy”. Ale nadal nie rozumiem, dlaczego property9 <- locations$xdziała, gdy names(locations)nie zawiera żadnej kolumny o nazwiex
jirikadlec2
1
Podczas tworzenia SpatialPointDataFrame przypisujesz xiy jako nazwy współrzędnych. Jeśli spojrzysz na lokalizację @ współrzędne, zobaczysz macierz ze współrzędnymi. Ponadto, jeśli spróbujesz utworzyć nową kolumnę w @data o nazwie „x”, nie możesz, ponieważ jest ona już używana jako nazwa współrzędnej.
Guillermo Olmedo
Nadal nie rozumiem, jakiego rodzaju „magii” SpatialPointsDataFrameużywa obiekt, aby uzyskać dostęp do współrzędnych z $operatorem. Ale przynajmniej teraz czuję się bardziej komfortowo. Uruchomiłem następujący kod: colnames(locations@coords) <- c("easting","northing") Po uruchomieniu locations$eastingdaje mi wektor współrzędnych x i locations$northingdaje wektor współrzędnych y.
jirikadlec2
Myślę, że w pewien sposób R traktuje dwie kolumny dla współrzędnych jako dwie kolejne kolumny części ramki danych w SpatialPointsDataFrame. Właśnie dlatego możesz mieć kolumnę o tej samej nazwie w slocie @data
Guillermo Olmedo
1
Wygląda na to, że nazewnictwo kolumn w @coordsmacierzy SpatialPointsDataFramezależy od tego, jak SpatialPointsDataFrameobiekt został utworzony. Metoda pierwsza: coordinates(sdat) <- x ~ yzmieni nazwę kolumn na "coords.x1", "coords.x2". Metoda druga: sdat <- SpatialPointsDataFrame(xy, attributes)zachowa oryginalne nazwy kolumn z xymatrycy.
jirikadlec2