Question

Very simple question that I want to ask in a general way because it seems to be a recurrent problem, and I would be glad to find a generic way to do it. The problem is to convert a matrix of logicals, for instance, into a matrix of factors, for instance, but keeping the matrix structure: number of rows & columns, colnames, rownames. I would like something more straightforward than

X2 <- matrix(as.mode(X), ncol=ncol(X)); 
rownames(X2) <- rownames(X) ...

I already have figured out this problem for some cases, so I put it here, but some questions remain...

A. into (-->) factors is the one I don't have an easy way to do.

B. 1. logicals --> numeric: uses the '+0' trick

BoolMatrix <- matrix(c(TRUE,FALSE),nrow=3,ncol=2)
rownames(BoolMatrix) <- LETTERS[1:3]; colnames(BoolMatrix) <-LETTERS[11:12]
(NumMatrix <- BoolMatrix + 0)   

B. 2. numeric --> logical: uses directly the condition

NumMatrix <- matrix(1:6, ncol=2)
rownames(NumMatrix) <- LETTERS[1:3]; colnames(NumMatrix) <-LETTERS[11:12]
(BoolMatrix <- NumMatrix == 0) 

C. numeric <--> character: cannot do better than a 2 liner, directly changing the mode works (and would also work between logicals and numerics, but above solutions are more elegant)

CharMatrix <- NumMatrix
mode(CharMatrix) <-"character"
print(CharMatrix)

the last solution ("2 liner") works actually for anything that is not related to factors, for which I am having difficulties...

Any idea ? :-)

Was it helpful?

Solution

Use structure, which attaches a list of attributes to an arbitrary object. For a matrix, the attributes you want are dim and, optionally, dimnames.

Eg conversion of X to a matrix of factors:

m <- structure(factor(X), dim=dim(X), dimnames=dimnames(X))

OTHER TIPS

Building on @HongOoi's excellent answer, here's a function that will retain all attributes of the input matrix (incl. dimensions and dimension names) and change the data to the desired mode or to a numeric mode , factor class.

change.mat <- function(X,ch.fun) {
  do.call(structure,c(list(.Data=do.call(ch.fun,list(X))),attributes(X)))
}

Examples:

change.mat(NumMatrix,factor)
#  K L
#A 1 4
#B 2 5
#C 3 6
#Levels: 1 2 3 4 5 6

change.mat(NumMatrix,as.character)
#  K   L  
#A "1" "4"
#B "2" "5"
#C "3" "6"

change.mat(BoolMatrix,as.numeric)
#  K L
#A 1 0
#B 0 1
#C 1 0

You can simply copy the attributes:

NumMatrix <- matrix(1:6, ncol=2)
rownames(NumMatrix) <- LETTERS[1:3]; colnames(NumMatrix) <-LETTERS[11:12]

FacMatrix <- as.factor(NumMatrix)
attributes(FacMatrix) <- c(attributes(FacMatrix), attributes(NumMatrix))
print(FacMatrix)
#   K L
# A 1 4
# B 2 5
# C 3 6
# Levels: 1 2 3 4 5 6
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top