Juan Vidal
Juan Vidal

Reputation: 9

apply function in R

I want to apply a user defined function over a matrix object. I don't have desired results my input is a 4x4 matrix and I want to get as output a 4x4 matrix with the transformation defined in mapfun function

Where is my error?

Thanks in advance

mapfun <- function(val){
if (val == 1){
 res <- "A"  }
else{
 if (val == 2){
   res <- "B"
 } else
 {
   if (val == 3){
     res <- "C"
   } else
   {
    res <- "D"
  }
  }
}
return(res)
}

mat1 <- matrix(sample(c(1,2,3,4), 16, replace=T,  prob=c(0.25,0.25,0.25,0.25)),
          nrow=4, ncol=4)

mat2 <- apply(mat1, 1, FUN=mapfun)`

Upvotes: 0

Views: 90

Answers (3)

Michal Majka
Michal Majka

Reputation: 5471

You could try this (fun) solution as well. First you coerce input value to a character vector and then use repeatedly replace function and return the result as a matrix again. Maybe there is a way to trick replace function so that it would be used only once.

mapfun <- function(val) {
  res <- as.character(val)
  res <- replace(x = res, list = which(res == "1"), values = "A")
  res <- replace(x = res, list = which(res == "2"), values = "B")
  res <- replace(x = res, list = which(res == "3"), values = "C")
  res <- replace(x = res, list = which(res == "4"), values = "D")
  return(matrix(res, ncol = 4)) # ncol(val)
}

mat1 <- matrix(sample(c(1,2,3,4), 16, replace=T,  prob=c(0.25,0.25,0.25,0.25)),
               nrow=4, ncol=4)
mat1
mapfun(mat1)

Upvotes: 0

erasmortg
erasmortg

Reputation: 3278

This could probably work:

mat1[] <- mapply(mapfun,mat1)

Note that this will modify mat1, so you could make a copy of mat1 named mat2 and apply the function to mat2:

mat2<- mat1
mat2[] <- mapply(mapfun,mat1)

Upvotes: 1

akrun
akrun

Reputation: 886938

We can just the numeric values in 'mat1' as index to replace the corresponding 'LETTERS'. The output will be a vector which can be converted back to a matrix by assigning dim.

`dim<-`(LETTERS[mat1], dim(mat1))

Regarding the Warning message in the mapfun, it would be better to use ifelse instead of if/else as we are dealing with a vector of length greater than 1 in each row of 'mat1'.

 mapfun <- function(val){
  ifelse(val == 1, 'A', 
        ifelse(val==2, 'B',
           ifelse(val==3, 'C', 'D')))
   }
apply(mat1, 1, mapfun)

Upvotes: 3

Related Questions