Propriedades e operadores de SpatialPointsDataFrame em R

14

Eu criei um objeto do tipo SpatialPointsDataFrameusando o sppacote em R. No entanto, estou confuso sobre os @, $, . and []operadores e quando usá-los para acessar as diferentes propriedades do meu objeto. Aqui está o meu código de exemplo:

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

Alguém poderia me ajudar, quando usar os @, $, []operadores? Quando eu tento ler a documentação ?SpatialPointsDataFrameque eu posso ver as diferentes propriedades, tais como coordsou bboxmas estou confuso qual operadora @, $, []usar para acessar los ou modificá-los.

jirikadlec2
fonte
1
Como essa é realmente uma pergunta sobre Rsintaxe, ela não é específica para o sppacote ou seus objetos. Restá instalado com um tutorial: comece aí em sua pesquisa. A Web e a mídia impressa oferecem uma riqueza de recursos adicionais para o aprendizado R.
whuber

Respostas:

21

Os dados espaciais sp são objetos da classe S4 e são compostos de slots (chamados usando @) que contêm componentes da classe de recurso espacial que está sendo representada (por exemplo, @data contém atributos, @coords contêm pares de coordenadas, etc ...). Você pode retornar os nomes dos slots de nível superior usando slotNames (), mas não é recursivo e não retornará nomes de slots aninhados para objetos de classe de polígono. Cada slot pode conter uma classe de objeto diferente e, antes de operar nele, deve ser verificado usando str () ou class (). O slot @data é sempre um objeto data.frame e @coords é uma matriz, enquanto @polygons é um objeto de lista com slots adicionais (labpt, área, furo, ringDir e cordas).

Os slots disponíveis e a organização deles dependem de que tipo de classe de recurso está sendo representado. Os objetos SpatialPointsDataFrame são os mais básicos, enquanto os objetos SpatialPolygonsDataFrame têm aninhamento (como visto acima). Essa estrutura aninhada, representando cada polígono, deve ser considerada usando algo como sapply para operar em cada objeto da lista (polígono).

Aqui está um exemplo que usa sapply para retornar a área de cada polígono iterando pelos "polígonos" e depois pelos slots "área" aninhados.

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

No caso de objetos de polígono, uma vez que eles são armazenados como uma lista para cada polígono, você também pode usar a indexação de lista. Aqui está um exemplo para retornar o primeiro polígono (resultando em um objeto de classe "Polígono" e não SpatialPolygonsDataFrame):

sdat@polygons[[1]]

Nas versões mais recentes do sp, os desenvolvedores começaram, em alguns casos, removendo a necessidade de chamar o slot @data diretamente.

Por exemplo, para indexar @ dados você anteriormente:

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

e agora:

sdat[sdat$att >= 0.5 ,]

No entanto, como indicado anteriormente, este não é o caso dos outros slots (por exemplo, coordenadas, polígonos, etc ...). Quanto a quando usar [] ou $, isso ainda depende do tipo de operação. Os colchetes "[]" podem ser usados ​​para chamar um nome em um quadro de dados, mas são usados ​​principalmente para indexação, enquanto $ é usado especificamente para chamar uma coluna em um quadro de dados. O motivo pelo qual uma chamada "indireta" para um nome de coluna funciona é que os desenvolvedores adicionaram funcionalidade para permitir uma pesquisa recursiva através do objeto sp. No entanto, para evitar conflitos de nome (como no seu exemplo; ter colunas x, y no seu quadro de dados entraria em conflito com os nomes x, y nos nomes da matriz @coord), há alguma verificação de consistência interna que explica por que isso funciona apenas em alguns casos. instâncias.

Uma característica conveniente é que você pode subconjunto de um objeto espacial por meio de um índice de linha. Aqui estou subconjunto dos 10 primeiros objetos.

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

Ou, alternativamente, uma amostra aleatória (n = 10) usando um vetor de índice de linha.

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

Compreender a indexação e como usar colchetes é uma coisa muito importante na escrita do código R.

Editar (24/03/2017): Observe que a classe de recurso simples (sf), seguindo o padrão GeoJSON, provavelmente se tornará o novo padrão para objetos espaciais em R. Você pode ler uma descrição detalhada dessa classe no CRAN sf website simples caracteriza por R .

Jeffrey Evans
fonte
Obrigado por uma explicação detalhada do que está acontecendo nos bastidores. Parece que SpatialPointsDataFramenão apenas as colunas @data, mas também as colunas @coords podem ser recuperadas com o $operador sem a necessidade de chamar o slot @coords. Então, sdat@coords$eastingdá o mesmo resultado que sdat$easting.
jirikadlec2
Parece que você está chamando uma coluna em <at> dados. Não é o mesmo que o slot de cabos <at>. Você notará que, se chamar colnames (sdat <at> coords), retornará os nomes das colunas da matriz: "coords.x1", "coords.x2". Não é necessário manter coordenadas no quadro de dados e, uma vez duplicado, uma cintura de memória.
Jeffrey Evans
Não. Não estou chamando a coluna nos dados <at>. Usando o SpatialPointsDataFrame do meu script de exemplo, colnames(locations@coords)retorna [1] "x" "y"mas colnames(locations@data)retorna [1] "v1" "v2". Talvez o comportamento dependa de qual função foi usada para criar o SpatialPointsDataFrame?
jirikadlec2
Na verdade, eu tenho um erro no meu primeiro comentário. sdat@coords$eastingnão funciona porque sdat @ coords é uma matriz. Mas sdat@coords[,"easting"]é equivalente a sdat@coords[,1]e para sdat$easting.
jirikadlec2
Uma ressalva, colnames () é usada para retornar nomes de colunas em uma matriz, enquanto names () retornará NULL. Embora ambos, names () e colnames () funcionem em um objeto de quadro de dados, como <at> data. A melhor maneira de recuperar dados da matriz <at> coord é indexá-los: sdat <at> coords [, 1] ou pelo nome da coluna sdat <at> coords [, "coords.x1"], mas como você observou $ não funciona porque é um objeto de matriz.
26414 Jeffrey Evans
4

Você deve tentar str(locations)esclarecer isso.

por exemplo, estes estão corretos:

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

E este property1 <- locations$v1funciona, porque está fazendo referência ao data.frame dentro da localização, @data

Guillermo Olmedo
fonte
str(locations)me deu algumas boas dicas. Agora eu entendo que @é usado para "slot de uma classe". Mas eu ainda não entendo por que property9 <- locations$xfunciona quando names(locations)não contém qualquer coluna chamadax
jirikadlec2
1
Ao criar o SpatialPointDataFrame, você atribui x e y como nomes de coordenadas. Se você olhar para locais @ cordas, poderá ver a matriz com as coordenadas. Além disso, se você tentar criar uma nova coluna no @data com o nome "x", não poderá, porque ele já será usado como nome da coordenada.
Guillermo Olmedo
Ainda não entendo que tipo de 'mágica' o SpatialPointsDataFrameobjeto usa para acessar as coordenadas com o $operador. Mas pelo menos estou mais confortável em usá-lo agora. Executei o seguinte código: colnames(locations@coords) <- c("easting","northing") Depois de executá-lo, locations$eastingo vetor da coordenada x e o vetor da coordenada locations$northingy.
jirikadlec2
Eu acho que, de alguma forma, R considera as duas colunas para as coordenadas como mais duas colunas da parte do quadro de dados do SpatialPointsDataFrame. É por isso que você pode ter uma coluna com o mesmo nome no slot @data #
Guillermo Olmedo
1
Parece que a nomeação das colunas na @coordsmatriz da SpatialPointsDataFramedepende de como o SpatialPointsDataFrameobjeto foi criado. Método 1: coordinates(sdat) <- x ~ yrenomeie as colunas para "coords.x1", "coords.x2". Método dois: sdat <- SpatialPointsDataFrame(xy, attributes)preservará os nomes das colunas originais da xymatriz.
jirikadlec2