[R] Using apply with more than one matrix

arun smartpink111 at yahoo.com
Thu May 1 15:23:48 CEST 2014


Hi,
Sorry, a typo in the previous function:
---------------------------------
if (condition1[i] && !is.na(indx3)) {
            arr[x1][indx3] + m2[i]  ###### should be mat2[i]
        } else NA
 
-----------

Also, you can try:
library(plyr)
evaluateNew <- function(arr, mat1, mat2){
if (!all(dim(mat1) == dim(mat2))) {
        stop("both matrices should have equal dimensions")
    }
 indx1 <- unlist(alply(arr, c(1,2), function(x) {x[!is.na(x)][1]}))
condition1 <- !is.na(mat1) & mat1 > mat2
ifelse(condition1, indx1+mat2, NA)
}
evaluateNew(a1, m1, m2)

#    [,1] [,2]
#[1,]   NA 1.66
#[2,] 3.14   NA
A.K.




On Thursday, May 1, 2014 5:49 AM, arun <smartpink111 at yahoo.com> wrote:


Hi,

You may try:
evaluate <- function(arr, mat1, mat2) {
    if (!all(dim(mat1) == dim(mat2))) {
        stop("both matrices should have equal dimensions")
    }
    indx1 <- as.matrix(do.call(expand.grid, lapply(dim(arr), sequence)))
    indx2 <- paste0(indx1[, 1], indx1[, 2])
    condition1 <- !is.na(mat1) & mat1 > mat2
    ans <- sapply(seq_along(unique(indx2)), function(i) {
        x1 <- indx1[indx2 %in% unique(indx2)[i], ]
        indx3 <- which(!is.na(arr[x1]))[1]
        if (condition1[i] && !is.na(indx3)) {
            arr[x1][indx3] + m2[i]
        } else NA
    })
    dim(ans) <- dim(mat1)
    ans
}
evaluate(a1,m1,m2)
#     [,1] [,2]
#[1,]   NA 1.66
#[2,] 3.14   NA

A.K.



On Thursday, May 1, 2014 2:53 AM, "Waichler, Scott R" <Scott.Waichler at pnnl.gov> wrote:
> I would ask you to look at this loop-free approach and ask if this is not
> equally valid?
> 
> ans <- matrix(NA, ncol=2, nrow=2)
> ind.not.na <- which(!is.na(a1))
> ans[] <- condition1*a1[,,ind.not.na[1]]+ m2  # two matrices of equal
> dimensions, one logical.
>  ans
>      [,1] [,2]
> [1,]   NA 1.66
> [2,] 2.74   NA

Thanks, I am learning something.  I didn't know you could multiply a logical object by a numerical one.  But notice the answer is not the same as mine, because I am doing an operation on the vector of values a1[i,j,] first.  

I tried a modification on sapply below, but it doesn't work  because I haven't referenced the 3d array a1 properly.  So I guess I must try to get a 2d result from a1 first, then use that in matrix arithmetic.

Sapply or mapply may work, I haven't used these much and will try to learn better how to use them.  Your use of sapply looks good; but I'm trying to understand if and how I can bring in the operation on a1.  This doesn't work:

evaluate <- function(idx) {
  ind.not.na <- which(!is.na(a1[idx,])) ]))  # doesn't work; improper indexing for a1
  if(length(ind.not.na) > 0) {
    return(condition1*(a1[idx,ind.not.na[1]] + m2[idx]))  # doesn't work; improper indexing for a1
  }
}
vec <- sapply(seq(length(m2)), evaluate)

Scott Waichler


> -----Original Message-----
> From: David Winsemius [mailto:dwinsemius at comcast.net]
> Sent: Wednesday, April 30, 2014 8:46 PM
> To: Waichler, Scott R
> Cc: Bert Gunter; r-help at r-project.org
> Subject: Re: [R] Using apply with more than one matrix
> 
> 
> On Apr 30, 2014, at 6:03 PM, Waichler, Scott R wrote:
> 
> > Here is a working example with no random parts.  Thanks for your
> patience and if I'm still off the mark with my presentation I'll drop the
> matter.
> >
> > v <- c(NA, 1.5, NA, NA,
> >       NA, 1.1, 0.5, NA,
> >       NA, 1.3, 0.4, 0.9)
> > a1 <- array(v, dim=c(2,2,3))
> > m1 <- matrix(c(NA, 1.5, 2.1, NA), ncol=2, byrow=T)
> > m2 <- matrix(c(1.56, 1.64, 1.16, 2.92), ncol=2)
> > condition1 <- !is.na(m1)& m1 > m2
> >
> > ans <- matrix(NA, ncol=2, nrow=2) # initialize for(i in 1:2) {  for(j
> > in 1:2) {
> >    ind.not.na <- which(!is.na(a1[i,j,]))
> >    if(condition1[i,j] && length(ind.not.na) > 0) ans[i,j] <-
> > a1[i,j,ind.not.na[1]] + m2[i,j]  } } ans
> >     [,1] [,2]
> > [1,]   NA 1.66
> > [2,] 3.14   NA
> 
> I would ask you to look at this loop-free approach and ask if this is not
> equally valid?
> 
> ans <- matrix(NA, ncol=2, nrow=2)
> ind.not.na <- which(!is.na(a1))
> ans[] <- condition1*a1[,,ind.not.na[1]]+ m2  # two matrices of equal
> dimensions, one logical.
>  ans
>      [,1] [,2]
> [1,]   NA 1.66
> [2,] 2.74   NA
> >
> > Let me try asking again in words.  If I have multiple matrices or slices
> of 3d arrays that are the same dimension, is there a way to pass them all
> to apply, and have apply take care of looping through i,j?
> 
> I don't think `apply` is the correct function for this. Either `mapply` or
> basic matrix operation seem more likely to deliver correct results:
> 
> 
> > I understand that apply has just one input object x.  I want to work on
> more than one array object at once using a custom function that has this
> characteristic:  in order to compute the answer at i,j I need a result
> from higher order array at the same i,j.
> 
> If you want to iterate over matrix indices you can either use the vector
> version e.g. m2[3] or the matrix version, m2[2,1[.
> 
> vec <- sapply(seq(length(m2) , function(idx) m2[idx]*condition1[idx] )
> 
> 
> 
> > This is what I tried to demonstrate in my example above.
> >
> > Thanks,
> > Scott
> 
> David Winsemius
> Alameda, CA, USA

______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list