Bart
Bart

Reputation: 759

Control representation of custom S4 class in matrix

If I use a custom class, instantiate it, and add it to a matrix, can I control how the output looks?

For example, I have a class cell I instantiate and add to a matrix. When I show the matrix, it shows up as a questionmark. Can I control how this output looks?

setClass("cell", representation(a="character", b="character"))

setMethod("show", "cell",
          function(object) print(paste(object@a,'|',object@b))
)

cell1<-
  new("cell", a="hello", b="world")

mat1<-
  matrix(c(cell1))


> print(cell1)
[1] "hello | world"
> print(mat1)
     [,1]
[1,] ?  

Upvotes: 1

Views: 60

Answers (1)

BrodieG
BrodieG

Reputation: 52637

Unfortunately print does not appear to dispatch on the sub-components of an object after an initial dispatch, which is terribly annoying but likely done for efficiency reasons. Here is a work around:

setMethod("as.character", "cell", function(x, ...) paste(x@a, '|', x@b))    
cell_matrix <- function(...) {
  structure(matrix(...), class="cell_matrix")
}
print.cell_matrix <- function(x, ...) {
  mat.char <- lapply(x, as.character)      
  dim(mat.char) <- dim(x)
  print(mat.char)
}
mat1 <- cell_matrix(c(cell1, cell1, cell1, cell1), nrow=2)
mat1

Produces:

     [,1]            [,2]           
[1,] "hello | world" "hello | world"
[2,] "hello | world" "hello | world"

Here I got lazy and mixed S3 and S4 classes, but if you're doing this in a package, you may want to implement an S4 cellMatrix class, and define an as.character method for that class, rather than just for a single cell.

Note that this is likely to be relatively inefficient as you are creating objects for each cell, and you are then iterating through each cell. I would create vectors that contain all the a values for all cells, and all the b values for all cells, and then create logic that makes it look like the elements are individual. Things will be much faster that way.

Upvotes: 2

Related Questions