Come convertire un poligono spaziale in uno SpatialPolygonsDataFrame e aggiungere una colonna alla tabella degli attributi


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 

Sopra, prendo qualsiasi categoria che ha 4 e nella nuova colonna lo metto come 0.

A questo punto, voglio anche la colonna denominata ratingsper bc, dove occorrerà 0 se è all'interno del buffer e 1 se è all'esterno. Il problema è che bcè SpatialPolygonse non contiene la tabella degli attributi.

Ovviamente per aggiungere una colonna a un SpatialPolygonoggetto devi convertirlo in a SpatialPolygonsDataFrame, ma non so come.

Ho provato questo:

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

ma viene visualizzato questo errore:

row.names of data and Polygons IDs do not match 

1
Bene, se leggi l'aiuto per gBuffer sapresti che se byid = TRUE il risultato è uno SpatialPolygonsDataFrame.
Jeffrey Evans,

Risposte:


11

Che cosa hanno a che fare gli oggetti "coast", "ro" e "bc" con il tuo problema? Il problema potrebbe risiedere nel fatto che stai utilizzando "readShapeSpatial". Hai provato a leggereOGR in rgdal? Se stai leggendo un file di forma poligonale, readOGR genererà un oggetto SpatialPolygonsDataFrame.

Se in effetti, hai un oggetto SpatialPolygons e vuoi forzare SpatialPolygonsDataFrame, il frame di dati specificato dovrà avere i suoi rownames corrispondenti agli ID poligono nello slot poligoni. Ecco un breve esempio.

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

ho mostrato il resto del codice come "coast", "ro" e "bc" per aiutarti a farti un'idea di quello che sto cercando di fare in generale. ho bisogno di ottenere una risposta più mirata a ciò che sto chiedendo e sarebbe saggio usare le mie variabili per essere più comprensibile. Inoltre, qual è il problema con readOGR e readShapeSpatial? Il "bc" contiene il buffer delle strade che è l'oggetto spazialpolygons a cui ho bisogno di aggiungere la nuova colonna, quindi devo prima convertirlo in spatialPolygonsDataFrame.
gsa,

10

Provare:

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

match.ID evita il requisito di rownames per ID poligoni partita


4
Non essere contrario, non è apprezzato! Il motivo per cui sono state fornite risposte "complicate" è perché nel 2015, quando è stata affrontata la domanda, l'argomento match.ID non era disponibile nel metodo di coersione.
Jeffrey Evans,

7

È abbastanza semplice:

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" 

Quando si verifica l'errore: "row.names dei dati e gli ID poligoni non corrispondono", questa soluzione sembra essere utile: rinominare gli ID del frame di dati in modo che corrispondano agli ID dei poligoni:

newdata <- data.frame(whatever you want in here)
row.names(newdata) <- (however the new polygons are labeled)
polygons <- SpatialPolygonsDataFrame(polygons, newdata)

2
Non sono sicuro su un paio di passaggi qui. Questa coercizione è dubbia: as.data.frame (poligoni). Il tuo esempio sta costringendo l'oggetto nella stessa classe. Inoltre, in un esempio reale, si genererebbe un errore perché i rownames del dataframe non corrisponderebbero all'ID negli slot poligonali. Devi estrarre gli ID poligono e assegnarli ai rownames prima della coercizione.
Jeffrey Evans,

@JeffreyEvans, questo è un copia-incolla dal codice di lavoro. Nessun errore, tutto funziona. Leggi la documentazione su come SpatialPolygonsDataFrameviene creato.
SS_Rebelious

4
Ma, dal momento che usi readOGR nel tuo esempio, stai iniziando con SpatialPolygonsDataFrame e il frame di dati che sottoinsieme ha già i rownames corretti perché l'hai estratto dall'oggetto sp originale. È un esempio di paglia.
Jeffrey Evans,

@JeffreyEvans, ho modificato la mia risposta per chiarire il significato.
SS_Rebelious

vedi la mia ultima modifica nel post principale e dimmi che cosa ho fatto di sbagliato perché penso di averlo fatto in base al tuo commento ma dà errore. Usa le mie variabili per renderlo più comprensibile. Grazie
gsa,

0

Trovo che la seguente soluzione funzioni generalmente.

Innanzitutto, crea un frame di dati vuoto con ID come campo:

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

Quindi ottenere gli ID del poligono spaziale 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

Quindi utilizzare df come secondo argomento della funzione di conversione dello spazio dati spaziale:

spatial_df <- SpatialPolygonsDataFrame(bc, df)

Come dfe spatial_dfsono oggetti dataframe, le colonne possono essere facilmente aggiunte

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.