Propriétés et opérateurs SpatialPointsDataFrame dans R

14

J'ai créé un objet de type en SpatialPointsDataFrameutilisant le sppackage dans R. Cependant, je suis confus au sujet des @, $, . and []opérateurs et quand les utiliser pour accéder aux différentes propriétés de mon objet. Voici mon exemple de code:

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

Quelqu'un pourrait-il m'aider, quand utiliser les @, $, []opérateurs? Lorsque j'essaie de lire la documentation, ?SpatialPointsDataFrameje peux voir les différentes propriétés telles que coordsou, bboxmais je ne sais pas quel opérateur @, $, []utiliser pour y accéder ou les modifier.

jirikadlec2
la source
1
Parce que c'est vraiment une question de Rsyntaxe, elle n'est pas particulière au sppackage ou à ses objets. Rest installé avec un tutoriel: commencez là dans votre recherche. Le Web et la presse écrite offrent une multitude de ressources supplémentaires pour l'apprentissage R.
whuber

Réponses:

21

Les données spatiales sp sont des objets de classe S4 et sont constituées de créneaux (appelés à l'aide de @) qui contiennent des composants de la classe d'entités spatiales représentée (par exemple, @data contient des attributs, @coords contient des paires de coordonnées, etc.). Vous pouvez renvoyer les noms d'emplacements de niveau supérieur à l'aide de slotNames (), mais il n'est pas récursif et ne renverra pas de noms d'emplacements imbriqués pour les objets de classe de polygones. Chaque emplacement peut contenir une classe d'objets différente et, avant de l'utiliser, doit être vérifié à l'aide de str () ou class (). L'emplacement @data est toujours un objet data.frame et @coords est une matrice tandis que @polygons est un objet liste avec des emplacements supplémentaires (labpt, area, hole, ringDir et coords).

Les emplacements disponibles et leur organisation dépendent du type de classe d'entités représenté. Les objets SpatialPointsDataFrame sont les plus basiques, tandis que les objets SpatialPolygonsDataFrame ont une imbrication (comme vu ci-dessus). Cette structure imbriquée, représentant chaque polygone, doit être prise en compte en utilisant quelque chose comme sapply pour opérer sur chaque objet de liste (polygone).

Voici un exemple qui utilise sapply pour renvoyer la zone pour chaque polygone en itérant à travers les "polygones" puis, le ou les emplacements "zone" imbriqués.

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

Dans le cas des objets polygones, étant donné qu'ils sont stockés sous forme de liste pour chaque polygone, vous pouvez également utiliser l'indexation de liste. Voici un exemple pour renvoyer le premier polygone (résultant en un objet de classe "Polygon" et non SpatialPolygonsDataFrame):

sdat@polygons[[1]]

Dans les versions plus récentes de sp, les développeurs ont commencé, dans certains cas, à supprimer la nécessité d'appeler directement l'emplacement @data.

Par exemple, pour indexer @data vous avez précédemment:

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

et maintenant:

sdat[sdat$att >= 0.5 ,]

Cependant, comme indiqué précédemment, ce n'est pas le cas pour les autres créneaux (ex: coordonnées, polygones, etc ...). Quant à savoir quand utiliser [] ou $, cela dépend toujours du type d'opération. Les crochets "[]" peuvent être utilisés pour appeler un nom dans une trame de données mais sont principalement utilisés pour l'indexation tandis que $ est spécifiquement utilisé pour appeler une colonne dans une trame de données. La raison pour laquelle un appel "indirect" à un nom de colonne fonctionne, c'est que les développeurs ont ajouté des fonctionnalités pour permettre une recherche récursive à travers l'objet sp. Cependant, pour éviter les conflits de noms (comme dans votre exemple; avoir des colonnes x, y dans votre trame de données entrerait en conflit avec les noms x, y dans les noms de matrice @coord), il existe une vérification de cohérence interne qui explique pourquoi cela ne fonctionne que dans certains instances.

Une caractéristique pratique est que vous pouvez sous-définir un objet spatial via un index de ligne. Ici, je sous-ensemble les 10 premiers objets.

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

Ou, alternativement, un échantillon aléatoire (n = 10) utilisant un vecteur d'index de ligne.

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

Comprendre l'indexation et comment utiliser les crochets est une chose très importante pour écrire du code R.

Edit (24/03/2017): Veuillez noter que la classe d'entités simples (sf), suivant la norme GeoJSON, deviendra probablement la nouvelle norme pour les objets spatiaux en R. Vous pouvez lire une description détaillée de cette classe sur le CRAN sf site web simple Caractéristiques R .

Jeffrey Evans
la source
Merci pour une explication détaillée de ce qui se passe dans les coulisses. Il apparaît que SpatialPointsDataFramenon seulement les colonnes @data, mais aussi les colonnes @coords peuvent être récupérées avec l' $opérateur sans qu'il soit nécessaire d'appeler l'emplacement @coords. sdat@coords$eastingDonne donc le même résultat que sdat$easting.
jirikadlec2
Il semble que vous appeliez une colonne dans les données <at>. Ce n'est pas la même chose que l'emplacement <at> coords. Vous remarquerez que si vous appelez des noms de colonnes (sdat <at> coords), vous retournerez les noms des colonnes de la matrice: "coords.x1", "coords.x2". Il n'est pas nécessaire de conserver les coordonnées dans la trame de données et, comme il est dupliqué, une taille de mémoire.
Jeffrey Evans
Non. Je n'appelle pas la colonne dans les données <at>. À l'aide de SpatialPointsDataFrame de mon exemple de script, colnames(locations@coords)renvoie [1] "x" "y"mais colnames(locations@data)renvoie [1] "v1" "v2". Peut-être que le comportement dépend de la fonction qui a été utilisée pour créer le SpatialPointsDataFrame?
jirikadlec2
En fait, j'ai une erreur dans mon premier commentaire. sdat@coords$eastingne fonctionne pas car sdat @ coords est une matrice. Mais sdat@coords[,"easting"]est équivalent à sdat@coords[,1]et à sdat$easting.
jirikadlec2
Une mise en garde, colnames () est utilisée pour retourner les noms de colonne dans une matrice tandis que, names () renverra NULL. Bien que les noms () et les noms de colonnes () fonctionnent sur un objet de trame de données tel que les données <at>. La meilleure façon de récupérer des données de la matrice de coordonnées <at> est de les indexer: sdat <at> coords [, 1] ou par nom de colonne sdat <at> coords [, "coords.x1"] mais comme vous l'avez noté, $ le fait ne fonctionne pas car il s'agit d'un objet matriciel.
Jeffrey Evans
4

Vous devriez essayer str(locations)de clarifier cela.

par exemple, ceux-ci sont corrects:

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

Et celui-ci property1 <- locations$v1fonctionne, car il fait référence à l'emplacement interne data.frame, @data

Guillermo Olmedo
la source
str(locations)m'a donné de bons indices. Maintenant, je comprends que cela @est utilisé pour "slot d'une classe". Mais je ne comprends toujours pas pourquoi property9 <- locations$xfonctionne quand names(locations)ne contient aucune colonne nomméex
jirikadlec2
1
Lorsque vous créez le SpatialPointDataFrame, vous affectez x et y comme noms de coordonnées. Si vous regardez locations @ coords, vous pouvez voir la matrice avec les coordonnées. De plus, si vous essayez de créer une nouvelle colonne dans @data avec le nom "x", vous ne pouvez pas, car elle est déjà utilisée comme nom de coordonnée.
Guillermo Olmedo
Je ne sais toujours pas vraiment quel genre de «magie» l' SpatialPointsDataFrameobjet utilise pour accéder aux coordonnées avec l' $opérateur. Mais au moins, je suis plus à l'aise de l'utiliser maintenant. J'ai exécuté le code suivant: colnames(locations@coords) <- c("easting","northing") Après l'avoir exécuté, locations$eastingme donne le vecteur de coordonnées x et locations$northingme donne le vecteur de coordonnées y.
jirikadlec2
Je pense que d'une certaine manière, R considère les deux colonnes pour les coordonnées comme deux autres colonnes de la partie dataframe du SpatialPointsDataFrame. C'est pourquoi vous pouvez avoir une colonne du même nom dans la fente @data
Guillermo Olmedo
1
Il semble que la dénomination des colonnes dans la @coordsmatrice du SpatialPointsDataFramedépend de la façon dont l' SpatialPointsDataFrameobjet a été créé. Première méthode: coordinates(sdat) <- x ~ yrenommera les colonnes en "coords.x1", "coords.x2". Méthode 2: sdat <- SpatialPointsDataFrame(xy, attributes)conserve les noms de colonne d'origine de la xymatrice.
jirikadlec2