Как преобразовать пространственный полигон в SpatialPolygonsDataFrame и добавить столбец в таблицу атрибутов

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 

Выше я беру любую категорию, которая имеет 4, и в новом столбце ставлю ее как 0.

На данный момент, я хочу, чтобы столбец также был назван ratingsдля bc, где он будет принимать 0, если он внутри буфера, и 1, если он снаружи. Проблема в том, что он bcесть SpatialPolygonsи не содержит таблицы атрибутов.

Очевидно, что для добавления столбца к SpatialPolygonобъекту необходимо преобразовать его в a SpatialPolygonsDataFrame, но я не знаю как.

Я попробовал это:

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

но эта ошибка выскакивает:

row.names of data and Polygons IDs do not match 
Администрация общих служб
источник
1
Что ж, если вы прочитаете справку для gBuffer, вы будете знать, что если byid = TRUE, результатом будет SpatialPolygonsDataFrame.
Джеффри Эванс

Ответы:

11

Какое отношение имеют объекты "coast", "ro" и "bc" к вашей проблеме? Проблема может заключаться в том, что вы используете «readShapeSpatial». Вы пробовали readOGR в rgdal? Если вы читаете шейп-файл полигона, readOGR приведет к объекту SpatialPolygonsDataFrame.

Если у вас действительно есть объект SpatialPolygons, и вы хотите привести его к SpatialPolygonsDataFrame, то указанному фрейму данных потребуется, чтобы его имена строк соответствовали идентификаторам полигонов в слоте полигонов. Вот быстрый пример.

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
Джеффри Эванс
источник
я показал остальную часть кода, такую ​​как «coast», «ro» и «bc», чтобы помочь вам понять, что я пытаюсь сделать в целом. Мне нужно получить более точный ответ на то, что я спрашиваю, и было бы разумно использовать мои собственные переменные, чтобы быть более понятными. Плюс, каково дело с readOGR и readShapeSpatial? «Bc» содержит буфер дорог, который является объектом пространственных полигонов, к которым мне нужно добавить новый столбец, таким образом, я должен сначала преобразовать его в пространственныйPolygonsDataFrame.
gsa
10

Пытаться:

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

match.ID избегает требования имен строк для идентификатора полигонов соответствия

Фабиан
источник
4
Не будь наоборот, это не ценится! Причина, по которой были получены «сложные» ответы, заключается в том, что в 2015 году, когда вопрос был решен, аргумент match.ID был недоступен в методе принуждения.
Джеффри Эванс
7

Это довольно просто:

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" 

Когда возникает ошибка: «row.names данных и идентификаторы полигонов не совпадают», это решение кажется полезным: переименуйте идентификаторы кадра данных, чтобы они соответствовали идентификаторам полигонов:

newdata <- data.frame(whatever you want in here)
row.names(newdata) <- (however the new polygons are labeled)
polygons <- SpatialPolygonsDataFrame(polygons, newdata)
SS_Rebelious
источник
2
Не уверен на пару шагов здесь. Это принуждение сомнительно: as.data.frame (полигоны). Ваш пример приводит объект в тот же класс. Кроме того, в реальном примере вы бы выдавали ошибку, потому что имена строк информационного кадра не совпадали с идентификатором в слоте (ах) многоугольника. Вам нужно получить идентификаторы полигонов и назначить их именам строк перед применением.
Джеффри Эванс
@JeffreyEvans, это копия из рабочего кода. Ошибок нет, все работает. Просто прочитайте некоторую документацию о том, как SpatialPolygonsDataFrameсоздается.
SS_Rebelious
4
Но, так как вы используете readOGR в своем примере, вы начинаете с SpatialPolygonsDataFrame, а поднабор данных, который вы устанавливаете, уже имеет правильные имена строк, потому что вы извлекли его из исходного объекта sp. Это пример соломенного чучела.
Джеффри Эванс
@JeffreyEvans, я отредактировал свой ответ, чтобы уточнить смысл.
SS_Rebelious
посмотрите мое последнее изменение в основном посте и скажите мне, что я сделал не так, потому что я думаю, что сделал это в соответствии с вашим комментарием, но это дает ошибку. Используйте мои собственные переменные, чтобы сделать его более понятным. Спасибо
gsa
0

Я считаю, что следующее решение обычно работает.

Сначала создайте пустой фрейм данных с идентификатором в качестве поля:

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

Затем получите идентификаторы пространственного многоугольника 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

Затем используйте df в качестве второго аргумента функции преобразования пространственных данных:

spatial_df <- SpatialPolygonsDataFrame(bc, df)

Поскольку dfи spatial_dfявляются объектами dataframe, столбцы могут быть легко добавлены

user55570
источник