Coat
Coat

Reputation: 717

Replace Items In Matrix Based on Value

I have a matrix that contains integer values that represent the index of the item in an array and I'd like to switch out item 1 for the values[1] and so on for each item in the values array.

Some code to demonstrate what I'd like

> m = matrix(1:3, ncol=3, nrow=3)
> m
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3
> replace(m, 1="a", 2="b", 3="c")
> m
     [,1] [,2] [,3]
[1,] "a"  "a"  "a" 
[2,] "b"  "b"  "b" 
[3,] "c"  "c"  "c" 

Basically it takes 1 and turns it into "a" and so on. It seems like if I try to do this with a for loop it changes after the first iteration from int to string and since I'd like to do this with any object type that's not great behavior.

Upvotes: 0

Views: 92

Answers (2)

David Arenburg
David Arenburg

Reputation: 92282

I can think of three possibilities to solve this

m <- matrix(1:3, 3, 3) # Your data

1

Either define a function that will get a vector in the correct matching order (the first entry will match the first unique value in m, etc.)

vec <- c("Ralf", "Jhons", "Pete") 

Then you can define a simple function such as

Match_func <- function(x, y) "dim<-"(y[match(unique(x), seq_along(y))], dim(x))

Test

Match_func(m, vec)
#      [,1]    [,2]    [,3]   
# [1,] "Ralf"  "Ralf"  "Ralf" 
# [2,] "Jhons" "Jhons" "Jhons"
# [3,] "Pete"  "Pete"  "Pete" 

2

The second option will be to define your manual replace function, something like

Match_func2 <- function(x, ...) {
  temp <- list(...)[[1]]
  "dim<-"(temp[match(x, as.numeric(names(temp)))], dim(x)) 
}

Test

Match_func2(m, c("1" = "a", "2" = "b", "3" = "c"))
#      [,1] [,2] [,3]
# [1,] "a"  "a"  "a" 
# [2,] "b"  "b"  "b" 
# [3,] "c"  "c"  "c" 

3

You can also make a use of plyr::revalue

library(plyr)
Match_func3 <- function(x, ...) {
  temp <- list(...)[[1]]
  "dim<-"(revalue(as.character(x), temp), dim(x))
}

Test

Match_func3(m, c("1" = "a", "2" = "b", "3" = "c"))
#      [,1] [,2] [,3]
# [1,] "a"  "a"  "a" 
# [2,] "b"  "b"  "b" 
# [3,] "c"  "c"  "c" 

Note: The last approach is the safest in case you don't want to replace all the unique values

Upvotes: 2

Bryan Hanson
Bryan Hanson

Reputation: 6213

Here's an option, starting with a character matrix so that you don't need to worry about making a copy or coercion of the original matrix.

m = matrix(as.character(1:3), ncol=3, nrow=3)
old <- as.character(1:3)
new <- c("a", "b", "c")
for (i in 1:length(old)) {
    m <- ifelse(m == old[i], new[i], m)
    }

Upvotes: 0

Related Questions