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" <[EMAIL PROTECTED]>
> 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.

______________________________________________
[EMAIL PROTECTED] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html

______________________________________________ [EMAIL PROTECTED] mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html

Reply via email to