Como converter um polígono espacial em um SpatialPolygonsDataFrame e adicionar uma coluna à tabela 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 

Acima, eu pego qualquer categoria que tenha 4 e, na nova coluna, coloque-a como 0.

Nesse ponto, quero a coluna também nomeada ratingspara bc, onde será necessário 0 se estiver dentro do buffer e 1 se estiver fora. O problema é que o bcé SpatialPolygonse não contém a tabela de atributos.

Obviamente, para adicionar uma coluna a um SpatialPolygonobjeto, você deve convertê-la em a SpatialPolygonsDataFrame, mas não sei como.

Eu tentei isso:

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

mas este erro aparece:

row.names of data and Polygons IDs do not match 
gsa
fonte
1
Bem, se você ler a ajuda do gBuffer, saberá que, se byid = TRUE, o resultado será SpatialPolygonsDataFrame.
Jeffrey Evans

Respostas:

11

O que os objetos "coast", "ro" e "bc" têm a ver com o seu problema? O problema pode estar no fato de você estar usando "readShapeSpatial". Você já tentou o readOGR no rgdal? Se você estiver lendo um shapefile de polígono, o readOGR resultará em um objeto SpatialPolygonsDataFrame.

Na verdade, se você possui um objeto SpatialPolygons e deseja coagir em SpatialPolygonsDataFrame, o dataframe especificado precisará que seus nomes de usuário correspondam aos IDs do polígono no slot de polígonos. Aqui está um exemplo 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
Jeffrey Evans
fonte
mostrei o restante do código como "coast", "ro" e "bc" para ajudar você a ter uma idéia do que estou tentando fazer em geral. Eu preciso obter uma resposta mais direta ao que estou perguntando e seria aconselhável usar minhas próprias variáveis ​​para ser mais compreensível. Além disso, qual é o problema do readOGR e do readShapeSpatial? O "bc" contém o buffer de estradas, que é o objeto de spatialpolygons ao qual preciso adicionar a nova coluna; portanto, tenho que convertê-la em um spatialPolygonsDataFrame primeiro.
GSA
10

Experimentar:

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

match.ID evita o requisito de nomes de nomes para ID de polígonos de correspondência

Fabián
fonte
4
Não seja contrário, não é apreciado! A razão pela qual respostas "complicadas" foram fornecidas é que, em 2015, quando a pergunta foi abordada, o argumento match.ID não estava disponível no método de coerção.
21418 Jeffrey Evans
7

É bem simples:

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 o erro: "row.names de dados e IDs de polígonos não coincidem" surge, esta solução parece útil: renomeie os IDs do quadro de dados para corresponder aos IDs dos polígonos:

newdata <- data.frame(whatever you want in here)
row.names(newdata) <- (however the new polygons are labeled)
polygons <- SpatialPolygonsDataFrame(polygons, newdata)
SS_Rebelious
fonte
2
Não tenho certeza em algumas etapas aqui. Essa coerção é duvidosa: as.data.frame (polígonos). Seu exemplo é coagir o objeto na mesma classe. Além disso, em um exemplo real, você geraria um erro porque os nomes de nomes de arquivo de dados não corresponderiam ao ID no (s) slot (s) de polígono. Você precisa puxar os IDs dos polígonos e atribuí-los aos nomes de domínio antes da coerção.
Jeffrey Evans
@ JeffreyEvans, esta é uma cópia e colar do código de trabalho. Sem erros, tudo está funcionando. Basta ler alguma documentação sobre como SpatialPolygonsDataFrameé criado.
SS_Rebelious 04/04
4
Mas, como você usa o readOGR no seu exemplo, você está começando com um SpatialPolygonsDataFrame e o dataframe que o subconjunto já possui os nomes de nome de usuário corretos, porque você o retirou do objeto sp original. É um exemplo de palhaço.
Jeffrey Evans
@JeffreyEvans, editei minha resposta para esclarecer o significado.
SSD_Rebelious
veja minha última edição no post principal e me diga o que fiz de errado, porque acho que fiz de acordo com o seu comentário, mas dá erro. Use minhas próprias variáveis ​​para torná-lo mais compreensível. Graças
GSA
0

Acho que a seguinte solução geralmente funciona.

Primeiro, crie um quadro de dados vazio com o ID como campo:

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

Em seguida, obtenha os IDs do 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

Em seguida, use df como o segundo argumento para a função de conversão espacial do quadro de dados:

spatial_df <- SpatialPolygonsDataFrame(bc, df)

Como dfe spatial_dfsão objetos de quadro de dados, as colunas podem ser facilmente adicionadas

user55570
fonte