Comment convertir un polygone spatial en un SpatialPolygonsDataFrame et ajouter une colonne à la table attributaire

19
coast<-readShapeSpatial("coastline.shp")
landc<-readShapeSpatial("landcover.shp")
ro<-readShapeSpatial("roads.shp")
bc<-gBuffer(ro,width=100)
landc$ratings=1
landc$ratings[landc$LANDUSE_ID==4]=0 

Ci-dessus, je prends n'importe quelle catégorie qui a 4 et dans la nouvelle colonne, je la mets à 0.

À ce stade, je veux que la colonne soit également nommée ratingspour le bc, où elle prendra 0 si elle est à l'intérieur du tampon et 1 si elle est à l'extérieur. Le problème est que le bcest SpatialPolygonset qu'il ne contient pas la table attributaire.

Évidemment, pour ajouter une colonne à un SpatialPolygonobjet, vous devez la convertir en un SpatialPolygonsDataFrame, mais je ne sais pas comment.

J'ai essayé ceci:

buf_df<-as.data.frame(bc)
s_po<-SpatialPolygonsDataFrame(bc,buf_df)
s_po$ratings=0

mais cette erreur apparaît:

row.names of data and Polygons IDs do not match 
gsa
la source
1
Eh bien, si vous lisez l'aide de gBuffer, vous saurez que si byid = TRUE le résultat est un SpatialPolygonsDataFrame.
Jeffrey Evans

Réponses:

11

Qu'est-ce que les objets "côte", "ro" et "bc" ont à voir avec votre problème? Le problème peut résider dans le fait que vous utilisez "readShapeSpatial". Avez-vous essayé readOGR dans rgdal? Si vous lisez un fichier de formes de polygones, readOGR produira un objet SpatialPolygonsDataFrame.

Si vous avez en fait un objet SpatialPolygons et que vous souhaitez contraindre SpatialPolygonsDataFrame, le cadre de données spécifié devra avoir ses noms de correspondance correspondant aux ID de polygone dans l'emplacement des polygones. Voici un petit exemple.

library(sp)

# create some SpatialPolygons with ID's "2" and "3"
( p <- SpatialPolygons(list(Polygons(list(Polygon(cbind(c(2,4,4,1,2),c(2,3,5,4,2)))), "2"),
     Polygons(list(Polygon(cbind(c(5,4,2,5),c(2,3,2,2)))), "3"))) )
class(p)    

# Create a dataframe and display default rownames
( p.df <- data.frame( ID=1:length(p)) ) 
rownames(p.df)

# Try to coerce to SpatialPolygonsDataFrame (will throw error)
p <- SpatialPolygonsDataFrame(p, p.df) 

# Extract polygon ID's
( pid <- sapply(slot(p, "polygons"), function(x) slot(x, "ID")) )

# Create dataframe with correct rownames
( p.df <- data.frame( ID=1:length(p), row.names = pid) )    

# Try coersion again and check class
 p <- SpatialPolygonsDataFrame(p, p.df)
 class(p) 

# Now we can add a column
p@data$ratings <- 1:2 

# Or modify an existing one
p[p$ID < 2 ,] <- 5
Jeffrey Evans
la source
j'ai montré le reste du code comme les "côtes", "ro" et "bc" pour vous aider à avoir une idée de ce que j'essaie de faire en général. J'ai besoin d'obtenir une réponse plus précise à ce que je demande et il serait sage d'utiliser mes propres variables afin d'être plus compréhensible. De plus, quel est le problème avec le readOGR et le readShapeSpatial? Le "bc" contient le tampon des routes qui est l'objet spatialpolygons auquel j'ai besoin d'ajouter la nouvelle colonne, donc je dois d'abord le convertir en spatialPolygonsDataFrame.
gsa
10

Essayer:

#Code taken from the question:
s_po <- SpatialPolygonsDataFrame(bc, buf_df, match.ID = F) 

match.ID évite la nécessité de renommer les ID des polygones de correspondance

Fabien
la source
4
Ne soyez pas contraire, ce n'est pas apprécié! La raison pour laquelle des réponses «compliquées» ont été fournies est qu'en 2015, lorsque la question a été abordée, l'argument match.ID n'était pas disponible dans la méthode de conversion.
Jeffrey Evans
7

C'est assez simple:

library("rgdal")
polygons <- readOGR('path_to/file.shp',
                      layer = 'file')
class(polygons)
>[1] "SpatialPolygonsDataFrame"
>attr(,"package")
>[1] "sp"

poly_df <- as.data.frame(polygons)
# do some staff with "poly_df" that doesn't support SpatialPolygonsDataFrame
# then convert it to SPDF back again
s_poly <- SpatialPolygonsDataFrame(polygons, poly_df)
# add new column to SPDF:
s_poly$new_column <- "some data" 

Lorsque l'erreur: "row.names of data and Polygons IDs do not match" survient, cette solution semble être utile: renommer les ID de la trame de données pour correspondre aux ID des polygones:

newdata <- data.frame(whatever you want in here)
row.names(newdata) <- (however the new polygons are labeled)
polygons <- SpatialPolygonsDataFrame(polygons, newdata)
SS_Rebelious
la source
2
Je ne sais pas sur quelques étapes ici. Cette contrainte est douteuse: as.data.frame (polygones). Votre exemple contraint l'objet dans la même classe. De plus, dans un exemple réel, vous généreriez une erreur car les noms de domaine de la trame de données ne correspondraient pas à l'ID dans le ou les emplacements de polygone. Vous devez extraire les ID de polygone et les affecter aux noms de domaine avant la coercition.
Jeffrey Evans
@JeffreyEvans, il s'agit d'un copier-coller du code de travail. Aucune erreur, tout fonctionne. Lisez simplement la documentation sur la SpatialPolygonsDataFramecréation.
SS_Rebelious
4
Mais, puisque vous utilisez readOGR dans votre exemple, vous commencez avec un SpatialPolygonsDataFrame et le sous-ensemble de données que vous sous-ensemble a déjà les noms d'utilisateur corrects car vous l'avez tiré de l'objet sp d'origine. C'est un exemple de paille.
Jeffrey Evans
@JeffreyEvans, j'ai modifié ma réponse pour clarifier le sens.
SS_Rebelious
voir ma dernière modification dans le post principal et dites-moi ce que j'ai fait de mal car je pense que je l'ai fait selon votre commentaire mais cela donne une erreur. Utilisez mes propres variables pour le rendre plus compréhensible. Merci
gsa
0

Je trouve que la solution suivante fonctionne généralement.

Créez d'abord une trame de données vide avec l'ID comme champ:

df <- data.frame(ID=character(), stringsAsFactors=FALSE )

Obtenez ensuite les identifiants du polygone spatial bc:

for (i in bc@polygons ) { df <- rbind(df, data.frame(ID=i@ID, stringsAsFactors=FALSE))  }
# and set rowname=ID
row.names(df) <- df$ID

Utilisez ensuite df comme deuxième argument de la fonction de conversion de trame de données spatiales:

spatial_df <- SpatialPolygonsDataFrame(bc, df)

Comme dfet spatial_dfsont des objets de trame de données, les colonnes peuvent être facilement ajoutées

user55570
la source