Преобразование SpatialPointsDataFrame в SpatialLinesDataFrame в R

#r #spatial

#r #пространственный

Вопрос:

Я работаю с набором данных HURDAT для построения треков ураганов. В настоящее время я создал объект SpatialPointsDataFrame в R, который выглядит примерно так для 2004 года.

     > str(cluster.2004.sdf)
Formal class 'SpatialPointsDataFrame' [package "sp"] with 5 slots
  ..@ data       :'data.frame': 2693 obs. of  4 variables:
  .. ..$ Sid      : int [1:2693] 1331 1331 1331 1331 1331 1331 1331 1331 1331 1331 ...
  .. ..$ clusterid: num [1:2693] 2 2 2 2 2 2 2 2 2 2 ...
  .. ..$ name     : Factor w/ 269 levels "","ABBY      ",..: 6 6 6 6 6 6 6 6 6 6 ...
  .. ..$ WmaxS    : num [1:2693] 78.9 82.8 80.9 70.9 76.9 ...
  ..@ coords.nrs : num(0) 
  ..@ coords     : num [1:2693, 1:2] 754377 612852 684956 991386 819565 ...
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : NULL
  .. .. ..$ : chr [1:2] "lon" "lat"
  ..@ bbox       : num [1:2, 1:2] -3195788 1362537 4495870 9082812
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : chr [1:2] "lon" "lat"
  .. .. ..$ : chr [1:2] "min" "max"
  ..@ proj4string:Formal class 'CRS' [package "sp"] with 1 slots
  .. .. ..@ projargs: chr " proj=lcc  lat_1=60  lat_2=30  lon_0=-60  ellps=WGS84"

    > summary(cluster.2004.sdf)
Object of class SpatialPointsDataFrame
Coordinates:
         min     max
lon -3195788 4495870
lat  1362537 9082812
Is projected: TRUE 
proj4string :
[ proj=lcc  lat_1=60  lat_2=30  lon_0=-60  ellps=WGS84]
Number of points: 2693
Data attributes:
      Sid         clusterid             name         WmaxS       
 Min.   :1331   Min.   :1.000   IVAN      :517   Min.   : 14.83  
 1st Qu.:1334   1st Qu.:2.000   FRANCES   :403   1st Qu.: 31.35  
 Median :1337   Median :3.000   JEANNE    :379   Median : 50.04  
 Mean   :1337   Mean   :2.898   KARL      :283   Mean   : 61.66  
 3rd Qu.:1339   3rd Qu.:4.000   DANIELLE  :271   3rd Qu.: 90.40  
 Max.   :1341   Max.   :4.000   BONNIE    :253   Max.   :142.52  
                                (Other)   :587 
  

У каждого шторма есть уникальная ссылка на идентификатор шторма, помеченная как «Sid».
Я хотел бы сгруппировать SpatialPointsDataFrame по «Sid» и преобразовать все точки в линию.

Я попробовал ddply из пакета plyr, но, честно говоря, понятия не имею, что я делаю. Я знаю, что могу сделать это, обводя каждую строку во фрейме данных и добавляя координаты в список, а затем преобразуя этот список с помощью функции Lines из пакета sp.

Тем не менее, я бы предпочел более R-способ преобразования. Спасибо, Ричард

Комментарии:

1. Все «R-способы» в конечном итоге имеют дело со списком, но вы можете использовать split(x, id) в качестве начала. Более важно, хотите ли вы простые (вероятно) или сложные строки. Вам нужна строка данных атрибутов для каждого уникального идентификатора? (просто)

Ответ №1:

Проблема с решением mdsumner заключается в том, что результирующий data.frame должен иметь одну строку для каждой строки, но в его коде есть одна строка для каждой точки. Исправленный код будет:

 ## example data
d <- data.frame(x=runif(7), y=runif(7), id = c(rep("a", 3), rep("b", 4)))

library(sp)    
coordinates(d) <- ~x y

## list of Lines per id, each with one Line in a list
x <- lapply(split(d, d$id), function(x) Lines(list(Line(coordinates(x))), x$id[1L]))

# the corrected part goes here:
lines <- SpatialLines(x)
data <- data.frame(id = unique(d$id))
rownames(data) <- data$id
l <- SpatialLinesDataFrame(lines, data)
  

Итак, проблема в основном заключается в том, что вам нужно создать data.frame для строк, сгруппированных по идентификатору (по одной строке для каждой строки). В приведенном выше случае, когда нет никаких данных, кроме, id это довольно просто. Если вам нужно сгруппировать некоторые другие данные по сравнению с оригиналом SpatialPointDataFrame , вы должны использовать некоторые функции группировки, такие как tapply , aggregate , или использовать мой любимый — sqldf :

 data <- sqldf('
select id, max(something), sum(something_else)
from d
group by id
')
  

Комментарии:

1. Спасибо. Я должен был отметить это как ответ, но также проголосовать за mdsumner.

Ответ №2:

 ## example data
d <- data.frame(x=runif(7), y=runif(7), id = c(rep("a", 3), rep("b", 4)))
##split(d, d$id)

library(sp)    
coordinates(d) <- ~x y

## list of Lines per id, each with one Line in a list
x <- lapply(split(d, d$id), function(x) Lines(list(Line(coordinates(x))), x$id[1L]))

## or one Lines in a list, with all Line objects
## x <- list(Lines(lapply(split(d, d$id), function(x) Line(coordinates(x))), paste(unique(d$id), collapse = "_")))

## etc.
SpatialLines(x, CRS(as.character(NA)))

## need to be careful here, assuming one Lines per original row
## and we trash the original rownames  . . .
SpatialLinesDataFrame(SpatialLines(x, CRS(as.character(NA))), d[,"id", drop = FALSE], match.ID = FALSE)
  

Комментарии:

1. @mdsummer. Спасибо за ответ. Кажется, я не могу заставить ваш код работать. Если я копирую точно строку за строкой и запускаю в R, я получаю сообщение об ошибке: > SpatialLinesDataFrame(SpatialLines(x, CRS(as.character(NA))), d[,»id», drop = FALSE], совпадение. ID = FALSE) Ошибка в SpatialLinesDataFrame(SpatialLines(x, CRS(as.character(NA))), : длина данных.кадр не соответствует количеству элементов строк

Ответ №3:

Из фрейма данных пространственных точек в фрейм данных пространственных полигонов

 library(sp)
library(raster)

### Example data: creating a SpatialPointsDataFrame object
x = c(1,2,5,4,3)
y = c(3,2,3,6,6)
df_points <- as.data.frame(cbind(x,y))
S <- SpatialPoints(cbind(x,y))
# S <- SpatialPoints(list(x,y))
# S <- SpatialPoints(data.frame(x,y))
S
plot(S)
spdf <- SpatialPointsDataFrame(S, df_points)
spdf
plot(spdf)
# crs(spdf) <- (" proj=utm  zone=23  south  datum=WGS84  units=m  no_defs") ### add a crs

### Convert the SpatialPointsDataFrame to SpatialPolygons
(Sr1 = Polygon(spdf[,1:2]))
(Srs1 = Polygons(list(Sr1), "s1"))
(SpP = SpatialPolygons(list(Srs1), 1:1, proj4string= crs(" proj=utm  zone=23  south  datum=WGS84  units=m  no_defs"))) 
plot(SpP, col = 3:3, pbg="white", add=T) 
SpP ### can not write as shapefile

### Convert the SpatialPolygons to SpatialPolygonsDataFrame
shape_pol <- SpatialPolygonsDataFrame(SpP, match.ID=F, data= data.frame(x=spdf[1:1,1], y=spdf[1:1,2]))
shape_pol ### can be write as shapefile
plot(shape_pol, col = 4, add=T)

### write shapefile
library(rgdal)
writeOGR(shape_pol, paste0(getwd(), "/Output_shapes"), "p_to_shape_pol", driver="ESRI Shapefile")