[R] IFELSE across large array?
Sander Oom
sander at oomvanlieshout.net
Sun Dec 5 19:14:51 CET 2004
Dear all,
Thanks to the help from the R mailing list we now have a script performing
the required tasks, i.e. applying a mask and filter to a 3D array. See
script below. Any further suggestions to simplify the code are very
welcome. We are currently debugging the larger script of which this section
is a small part.
The script could serve as a framework for many typical GIS neighborhood
analyses, in this case the 'block majority'. The 'var.range' variable is
derived from variography earlier in the main script.
Yours,
Sander and Alessandro
##########INPUT SECTION1##############################
numRow<-7
numCol<-8
numReal<-2
var.range<- 2.1
cellsize<- 0.25
################################################
##CALCULATE WINDOW SIZES BASED ON INPUT ABOVE#####
#window size ...minimum is 1
numCells<-round((var.range*cellsize)/2,0)
if(numCells < 1) {numCells<-1}
###################################################
library(abind)
#Sim: 0=Absent; 1=Present; 10=NA
vectSim <- c(1,1,0,0,1,1,10,1,0,10,1,1,1,0,1,1,1,1,1,0,0,1,0,0,10,0,0,
1,1,1,0,1,1,0,0,0,1,1,1,0,1,1,0,1,0,1,10,0,1,0,0,1,0,0,10,0,0,0,1,1,0,
0,1,0,1,0,0,1,0,0,1,1,1,1,1,10,1,10,1,0,1,0,1,0,0,1,1,0,10,10,1,1,0,1,
0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,0)
#Mask: 10=NA; 1=DATA
vectMask <- c(10,1,10,1,1,10,1,10,1,10,10,1,10,1,10,1,1,10,1,10,1,10,10,1,10,1,
10,1,1,10,1,10,1,10,10,1,10,1,10,1,1,10,1,10,1,10,10,1,10,1,10,1,1,10,1,10)
length(vectSim)
length(vectMask)
Sim <- array(vectSim, c(numRow,numCol,numReal))
Sim[Sim==10]<-NA
Sim
Mask <- array(data=vectMask, c(numRow,numCol,numReal))
Mask
##expand array
junkcol<-array(rep(NA,numReal*numRow),c(numRow,numCells,numReal))
#add columns borders
#cols
Sim<-abind(junkcol,Sim,junkcol, along=2)
dim(Sim)[2]
junkrow<-array(rep(NA,dim(Sim)[2]),c(numCells,dim(Sim)[2],numReal))
Sim<-abind(junkrow,Sim,junkrow,along=1)
##DEFINE PORTION OF ARRAY ON WHICH MOVING WINDOW RUNS
##IT AVOIDS THE na BORDER
#maximum row and col indexes to consider are equal
# to num num rows and num cols in the original matrix
minr<-1+numCells
maxr<-dim(Sim)[1]-numCells
minc<-1+numCells
maxc<-dim(Sim)[2]-numCells
clean<-function(a,nr,r,c) {
rmin<-row(a)[r-numCells]
rmax<-row(a)[r+numCells]
cmin<-col(a)[nr*(c-numCells)]
cmax<-col(a)[nr*(c+numCells)]
junk<-a[rmin:rmax,cmin:cmax]
junk[numCells,numCells]<-NA
junk<-as.vector(junk)
sample(na.omit(junk),1)
}
for (n in 1:numReal) {
realiz<-Sim[1:dim(Sim)[1],1:dim(Sim)[2],n]
rz<-realiz
for (r in minr:maxr) {
for (c in minc:maxc) {
if(is.na(realiz[r,c]) ) {
realiz[r,c]<-clean(a=realiz,nr=numRow,r=r,c=c)
Sim[1:dim(Sim)[1],1:dim(Sim)[2],n]<-realiz
}#end if
}
}
}##end overall loop
# Return to original array dimensions, removing extra NA
minr <- (numCells+1)
maxr <- (dim(Sim)[1]-numCells)
minc <- (numCells+1)
maxc <- (dim(Sim)[2]-numCells)
expSim <- Sim
expSim
Sim <- expSim[minr:maxr, minc:maxc, 1:dim(Sim)[3]]
Sim
# Clip simulation results using the mask
Mask
Sim[Sim==10] <- NA
Mask[Mask==10] <- NA
A <- Sim + Mask -1
A
#################################
At 01:55 2004/11/24, Ray Brownrigg wrote:
> > From: "Liaw, Andy" <andy_liaw at merck.com>
> > Date: Tue, 23 Nov 2004 12:28:48 -0500
> >
> > I'll give it half a crack:
> >
> > Steps a through c can be done via nested ifelse(), treating A and M as
> > vectors (as they really are). Step d is the hard one. I'd write a simple
> > Fortran code and use .Fortran() for that.
> >
> > I don't see how any of the *apply() functions can help here, as your
> > operations are element-wise, not dimension-wise.
> >
> > Andy
> >
>The original message mentions that the value 10 is actually "NODATA",
>and if one recodes 10 as NA, steps a) to c) become trivial, namely:
>
>A[A == 10] <- NA
>M[M == 10] <- NA
>return(A + M - 1)
>
>Then if step d) is performed first (i.e. appropriate values in A are
>replaced by the 'most common neighbour' [perhaps using
>round(mean(.., na.rm=T))] this still works, but would have to be repeated
>for each replication (the third dimension).
>
>Ray Brownrigg
>
> > > From: Sander Oom
> > >
> > > Dear all,
> > >
> > > As our previous email did not get any response, we try again with a
> > > reformulated question!
> > >
> > > We are trying to do something which needs an efficient loop
> > > over a huge
> > > array, possibly functions such as apply and related (tapply,
> > > lapply...?), but can't really understand syntax and examples in
> > > practice...i.e. cant' make it work.
> > >
> > > to be more specific:
> > > we are trying to apply a mask to a 3D array.
> > > By this I mean that when "overlaying" [i.e. comparing element
> > > by element]
> > > the mask on to the array the mask should change array
> > > elements according to
> > > the values of both array and mask elements
> > >
> > > the mask has two values: 1 and 10.
> > >
> > > the array elements have 3 values: 0, 1, or 10
> > >
> > > sticking for the moment to the single 2d array case
> > >
> > > for example:
> > > [A= array] 10 0 10 1 10 0
> > > 1 10 1 0 0 10
> > >
> > > [ M=mask] 1 10 10 1 1 1
> > > 10 1 1 1 10 10
> > >
> > > I would like the array elements to:
> > >
> > > a) IF A(ij) !=10 and Mij = 1
> > > leave A(ij) unchanged
> > >
> > > b) IF A(ij) != 10 and M(ij) =10
> > > change A(ij) to M(ij) i.e mask value (10)
> > >
> > > c)IF A(ij) = 10 and M(ij) = 10
> > > leave (Aij) unchanged
> > >
> > > d) IF A(ij) = 10 and M(ij) !=10
> > > replace A(ij) with the majority value in the
> > > 8-neighborhood
> > >
> > > (or whatever if it is an edge element) BUT ignoring 10s in this
> > > neighborhood (i.e. with either 1 or 0, whichever is in majority)
> > >
> > > because the array is 3d I would like to repeat the thing with
> > > all the k
> > > elements (2d sub-arrays) of the array in question, using the
> > > same mask for
> > > al k elements
> > >
> > > Would you be able to suggest a strategy to do this?
> > >
> > > thanks very much
> > >
> > > Alessandro and Sander.
>
>______________________________________________
>R-help at stat.math.ethz.ch mailing list
>https://stat.ethz.ch/mailman/listinfo/r-help
>PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
More information about the R-help
mailing list