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
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.
On Tue, 2004-11-23 at 12:28 -0500, Liaw, Andy wrote:
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
I'll toss in one additional thought here in follow up to Andy's, which
is that you could feasibly use mapply() to do element-wise operations.
In fact, this is how I compute concordant and discordant pairs in a 2D
matrix for some of the measures of association that I want to include in
the CrossTable() function in the gregmisc bundle.
I'll paste the code for the concordant() function here, to give you an
idea of the approach:
# Calculate CONcordant Pairs in a table
# cycle through x[r, c] and multiply by
# sum(x elements below and to the right of x[r, c])
# x = table
concordant <- function(x)
{
# get sum(matrix values > r AND > c)
# for each matrix[r, c]
mat.lr <- function(r, c)
{
lr <- x[(r.x > r) & (c.x > c)]
sum(lr)
}
# get row and column index for each
# matrix element
r.x <- row(x)
c.x <- col(x)
# return the sum of each matrix[r, c] * sums
# using mapply to sequence thru each matrix[r, c]
sum(x * mapply(mat.lr, r = r.x, c = c.x))
}
Presumably, you could extend the basic approach to a 3D structure, by
using a third index argument to the mapply() call and use something like
expand.grid() to create the three vectors for the indices into the 3D
array:
# Set up the index combinations for a 4 x 4 x 4 array
Index <- expand.grid(1:4, 1:4, 1:4)
YourFunction <- function(a, b, c)
{
DoSomethingHere(YourArray[a, b, c])
}
YourReturnVals <- mapply(YourFunction, a = Index[, 1], b = Index[, 2],
c = Index[, 3])
I am hoping that this approach might be applicable here, at least in
basic concept. Also, keep in mind any scoping issues with respect to
your data structures.
HTH,
Marc Schwartz