edzer / sp

Classes and methods for spatial data

Home Page:http://edzer.github.io/sp/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

as.SpatialPolygons.GridTopology returns different coordnames

andrewzm opened this issue · comments

Is it possible to make the function as.SpatialPolygons.GridTopology return an object with the same coordinate names as the object grd passed to it? This can be easily accomplished by extracting the names from the grd object and assigning them to the polygon objects when they're created (changes in bold):

as.SpatialPolygons.GridTopology <- function (grd, proj4string = CRS(as.character(NA)))
{
coord_names <- names(grd@cellsize)
grd_crds <- coordinates(grd)
IDs <- IDvaluesGridTopology(grd)
nPolygons <- nrow(grd_crds)
cS <- grd@cellsize
cS2 <- cS/2
cS2x <- cS2[1]
cS2y <- cS2[2]
Srl <- vector(mode = "list", length = nPolygons)
   for (i in 1:nPolygons) {
   xi <- grd_crds[i, 1]
   yi <- grd_crds[i, 2]
   x <- c(xi - cS2x, xi - cS2x, xi + cS2x, xi + cS2x, xi - cS2x)
   y <- c(yi - cS2y, yi + cS2y, yi + cS2y, yi - cS2y, yi - cS2y)
   coords <- cbind(x,y)
   colnames(coords) <- coord_names
   Srl[[i]] <- Polygons(list(Polygon(coords = coords)), ID = IDs[i])

   comment(Srl[[i]]) <- "0"
}
res <- SpatialPolygons(Srl, proj4string = proj4string)
res
}

I'm asking this as changing the coordinate names afterwards if the grid topology is not in "x" and "y" which can be much more time consuming than generating the SpatialPolygons themselves. Also, I don't think this should break any existing code.

Are you aware that coordnames(x) = c("xx", "yy") sets coordinate names?

Of course, the problem is that setting coordnames of SpatialPolygons for some reason takes a longer time than converting the GridTopology to SpatialPolygons in the first place. Here is a working example, where I have defined the function as.SpatialPolygons.GridTopology2() to be the modified function I posted earlier:

y <- x <- seq(0,1,length=200)
xy <- expand.grid(xcoords = x,ycoords = y)
xy_sp <- SpatialPoints(xy)
xy_grid <- points2grid(xy_sp)
system.time({
     xy_SpPols <- as.SpatialPolygons.GridTopology2(xy_grid)
})

user system elapsed
4.778 0.004 4.784

system.time({
     xy_SpPols <- as.SpatialPolygons.GridTopology(xy_grid)
     coordnames(xy_SpPols) <- c("xcoords","ycoords")
 })

user system elapsed
39.844 0.034 39.902

The problem arises because I'm trying to include sp in a package and I do not wish to coerce the user-defined coordnames to x and y half-way through the program if at all possible.

well, that's a strong case. A few more questions:

  • your solution removes coordinate names if names(grd@cellsize) is NULL, where in the current version they are set to x and y.
  • why retrieve names cellsize and not from grd@cellcentre.offset?
  • instead of solving the problem here, we might do it in coordnames<-

please test my latest two commits, which

  • optimize coordnames<- by avoiding method dispatch and
  • propagate names(grd@cellcentre.offset) to coordnames when coercing to SpatialPolygons

Thank you Edzer, it's much faster and comparable now. But there seems to be a problem with the new coordnames<-; following on from the previous example, when I then type

coordnames(xy_SpPols)

I now get the error

Error in (function (classes, fdef, mtable)  : 
unable to find an inherited method for function ‘coordnames’ for signature ‘"list"’

Originally xy_SpPols@polygons[[1]] was of class Polygons but with the new version it's of class list and simply contains the coordinate names instead of the polygon.

As to your previous comment, I don't see that returning an object with coordnames NULL if the initial object supplied by the user didn't have coordinate names as a problem (other than this might have other issues down the line). Also there was no particular reason why I retrieved the coordnames from grd@cellsize, I just chose one of the slots.

Another thought I have if you think this might break code is to just add an argument to this and all related methods an argument coordnames = c("x","y") which then can be altered for those who need it to be altered.

Thanks -- this should work now.

Thanks Edzer that works just fine. It's still twice as slow than if you assign the coordnames straight inside the loop as I did in my first post though (I assume coordnames goes through a loop again). Up to you, this is still a big improvement though!

OK, added it to the loop. It now also drops the rownames of the coords generated.

Works great Edzer, thanks for the quick response!