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)
isNULL
, where in the current version they are set tox
andy
. - why retrieve names
cellsize
and not fromgrd@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 toSpatialPolygons
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!