Cómo convertir un polígono espacial en un SpatialPolygonsDataFrame y agregar una columna a la tabla de atributos


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 

Arriba, tomo cualquier categoría que tiene 4 y en la nueva columna la pongo como 0.

En este punto, quiero que la columna también se nombre ratingspara bc, donde tomará 0 si está dentro del búfer y 1 si está afuera. El problema es que el bces SpatialPolygonsy no contiene la tabla de atributos.

Obviamente, para agregar una columna a un SpatialPolygonobjeto, debe convertirlo en a SpatialPolygonsDataFrame, pero no sé cómo.

Intenté esto:

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

pero aparece este error:

row.names of data and Polygons IDs do not match 

1
Bueno, si lees la ayuda para gBuffer sabrías que si byid = TRUE el resultado es un SpatialPolygonsDataFrame.
Jeffrey Evans el

Respuestas:


11

¿Qué tienen que ver los objetos "costa", "ro" y "bc" con su problema? El problema puede estar en que está utilizando "readShapeSpatial". ¿Has probado readOGR en rgdal? Si está leyendo un archivo de forma de polígono, readOGR generará un objeto SpatialPolygonsDataFrame.

Si, de hecho, tiene un objeto SpatialPolygons y desea forzarlo en SpatialPolygonsDataFrame, el marco de datos especificado necesitará que sus nombres de fila coincidan con los ID de los polígonos en la ranura de polígonos. Aquí hay un ejemplo rápido.

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

Mostré el resto del código como "costa", "ro" y "bc" para ayudarlo a tener una idea de lo que estoy tratando de hacer en general. Necesito obtener una respuesta más directa al punto de lo que estoy preguntando y sería prudente usar mis propias variables para ser más comprensible. Además, ¿cuál es el trato con el readOGR y el readShapeSpatial? El "bc" contiene el búfer de carreteras, que es el objeto de polígonos espaciales al que necesito agregar la nueva columna, por lo que primero debo convertirlo en un espacio de Polígonos de Datos espacial.
gsa

10

Tratar:

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

match.ID evita el requisito de nombres de fila para la identificación de polígonos de coincidencia


44
¡No seas contrario, no es apreciado! La razón por la que se proporcionaron respuestas "complicadas" es porque en 2015, cuando se abordó la pregunta, el argumento match.ID no estaba disponible en el método de coerción.
Jeffrey Evans

7

Es bastante 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" 

Cuando aparece el error: "los nombres de fila de datos y los ID de polígonos no coinciden", esta solución parece ser útil: cambie el nombre de los ID del marco de datos para que coincidan con los ID de los polígonos:

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

2
No estoy seguro en un par de pasos aquí. Esta coerción es dudosa: as.data.frame (polígonos). Su ejemplo es coaccionar el objeto en la misma clase. Además, en un ejemplo real, arrojaría un error porque los nombres de fila del marco de datos no coincidirían con la ID en las ranuras del polígono. Debe extraer los ID de polígono y asignarlos a los nombres de fila antes de la coerción.
Jeffrey Evans

@ JeffreyEvans, esta es una copia y pega del código de trabajo. Sin errores, todo está funcionando. Simplemente lea alguna documentación sobre cómo SpatialPolygonsDataFramese crea.
SS_Rebelious

44
Pero, dado que usa readOGR en su ejemplo, está comenzando con un SpatialPolygonsDataFrame y el marco de datos que subconjunto ya tiene los nombres de fila correctos porque lo extrajo del objeto sp original. Es un ejemplo de paja.
Jeffrey Evans

@JeffreyEvans, edité mi respuesta para aclarar el significado.
SS_Rebelious

vea mi última edición en la publicación principal y dígame qué hice mal porque creo que lo hice de acuerdo con su comentario, pero da error. Usar mis propias variables para hacerlo más comprensible. Gracias
gsa

0

Encuentro que la siguiente solución generalmente funciona.

Primero, cree un marco de datos vacío con ID como campo:

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

Luego obtenga las ID del polígono espacial 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

Luego use df como segundo argumento para la función de conversión de marco de datos espacial:

spatial_df <- SpatialPolygonsDataFrame(bc, df)

Como dfy spatial_dfson objetos de marco de datos, las columnas se pueden agregar fácilmente

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.