[R-sig-Geo] neighbourhood analysis with R spatial objects
Alexandre Villers
villers.alexandre at gmail.com
Fri Feb 17 11:37:13 CET 2012
Dear list,
I am struggling a bit with this issue and was hoping that someone could
indicate me a solution.
I have a raster image describing the landscape (with several habitat
classes) at 10 meters resolution. I would like to compute the different
proportions of each habitat type, but on a coarser grid (let's say 250
meters), each cell getting the proportions of habitat classes from
different buffer radii, taking the centre of each grid cell as
representative of the grid (might not be very accurate for small
buffers, but with the radii increasing, it should quickly be OK).
I used to do similar tasks with the r.neighbors function in GRASS but
the problem is that this time, I need to run it on the 10 meters
resolution grid (because some habitats are very scarce but a priori
relevant to the questions my colleague and I want to answer), meaning a
long computation time (already several days at 25 meters resolution),
most of which being useless (as r.neighbors in GRASS compute the
neighbourhood on all the pixels).
For the moment, I came up with this the code below, but this is not
efficient at all (57 seconds for a final grid of 400 cells as in the
example, mine containing ~20000 pixels...). Moreover, as written
earlier, I have 11 buffer radii and 16 images on which to batch.
Basically, I create a regular grid of points at 250 meters over the
SpatialGridDataFrame at 10 meters resolution, and then, loop over each
points (create a buffer, overlay with the raster to get the number of
pixels of each habitat class, fill the final raster with the proportion
after computations and save the object).
I'm not sure if this can be done more efficiently with GRASS (computing
the neighbourhood just for a set of locations, not for all pixels) and I
was hoping to be able to do that with R somehow. I couldn't find
anything in the discussion lists (with keywords "neighbourhood
analysis", "buffer raster", etc.) but maybe I missed something (with te
different possible approaches in sp, raster, spatstat, it is highly
probable).
Any link towards a potential solution that could speed up the
computations would be highly appreciated
Cheers
Alex
P.S.: the code below should give you an idea of what I would like to
achieve (but much faster if possible !)
library(sp)
#Create the environmental covariate
extent<-5000 #extent of the raster
sp.res<-10 #resolution of the raster
bb<-matrix(c(0,0,extent,extent), ncol=2, dimnames=list(NULL,
c("min","max")))
cs<-c(sp.res,sp.res) #the resolution of our grid of habitat
cc<-bb[,1] + (cs/2)
cd<-ceiling(diff(t(bb))/cs)
landGT.temp<-GridTopology(cellcentre.offset=cc, cellsize=cs, cells.dim=cd)
land.spg<-SpatialGrid(landGT.temp)
Habitat<-rpois(length(coordinates(land.spg)[,1]), 5) #create dummy
variable of integers for landscape category
land.spgdf<-SpatialGridDataFrame(land.spg, data.frame(Habitat=Habitat))
#create the final grid on which we want the data
sp.res.p<-250 #resolution of the raster
bb.p<-matrix(c(0,0,extent,extent), ncol=2, dimnames=list(NULL,
c("min","max")))
cs.p<-c(sp.res.p,sp.res.p) #the resolution of our grid of habitat
cc.p<-bb.p[,1] + (cs.p/2)
cd.p<-ceiling(diff(t(bb.p))/cs.p)
fgridGT.temp<-GridTopology(cellcentre.offset=cc.p, cellsize=cs.p,
cells.dim=cd.p)
fgrid.spg<-SpatialGrid(fgridGT.temp)
fgrid.spp<-as(fgrid.spg, "SpatialPoints")
#the idea is to get the proportion of the different habitats described
by land.spgdf in buffer of increasing radii
# such as in the example
image(land.spgdf)
plot(fgrid.spp[210,], col="black", add=T)
plot(gBuffer(fgrid.spp[210,], width=1000), add=T)
plot(gBuffer(fgrid.spp[210,], width=250), add=T)
n.points<-length(coordinates(fgrid.spp)[,1])
buffers<-c(250,1000)
n.hab.class<-length(unique(Habitat))
system.time(for (j in 1:length(buffers)){ #
temp.df<-as.data.frame(matrix(data=NA, nrow=n.points,
ncol=n.hab.class))
spgdf.res<-SpatialGridDataFrame(fgrid.spg, temp.df)
res.temp<-NULL
for (k in 1:n.points){ # n.points
buff.temp<-gBuffer(fgrid.spp[k,], width=buffers[j]) #create
the buffer for the kth point with radius buffers[j]
assol.buff<-land.spgdf$Habitat[!is.na(over(land.spgdf,
buff.temp))] #overlay and remove the useless NAs
n.pix<-tapply(assol.buff, assol.buff,
length)[as.character(sort(unique(Habitat)))][] #number of pixel per
habitat class (sorted)
res.temp<-rbind(res.temp,n.pix) #store the data in a
temporary array
}
spgdf.res at data[1:n.points,]<-res.temp;
spgdf.res at data[is.na(spgdf.res at data[,1:21])]<- 0 #replace the NAs
(absence of the habitat class) with zeros
spgdf.prop<-spgdf.res; spgdf.prop at data[,1:21]<-NA;
spgdf.prop at data[,1:21]<-t(apply(spgdf.res at data, 1, function(x)
x/sum(x))) #the last to get the proportion of habitat
name.temp<-paste("prop.",buffers[j],"m",sep="")
assign(name.temp, spgdf.prop) #create the final R object (that
could saved as well as GTiff or any other raster format)
rm(spgdf.res, name.temp, spgdf.prop, temp.df)
}
)
#An example
spplot(prop.250m, "V5")
More information about the R-sig-Geo
mailing list