Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an R matrix contain different datatypes? Does this hacked-up matrix-of-lists work?

Tags:

types

list

r

matrix

I read these:

  • https://stackoverflow.com/a/5159049/1175496

    Matrices are for data of the same type.

  • https://stackoverflow.com/q/29732279/1175496

    Vectors (and so matrix) can accept only one type of data

If matrix can only accept one data type, why can I do this:

> m_list<-matrix(list('1',2,3,4),2,2)
> m_list
     [,1] [,2]
[1,] "1"  3   
[2,] 2    4   

The console output looks like I am combining character and integer data types. The console output looks similar to this matrix:

> m_vector<-matrix(1:4,2,2)
> m_vector
     [,1] [,2]
[1,]   1    3   
[2,]   2    4   

When I assign to m_list, it doesn't coerce the other values (as in https://stackoverflow.com/q/29732279/1175496 )

> m_list[2,2] <-'4'
> m_list
     [,1] [,2]
[1,] "1"  3 
[2,] 2    "4"  
like image 708
The Red Pea Avatar asked Oct 26 '15 18:10

The Red Pea


2 Answers

OK here is what I gather from replies so far:

Question

How can I have a matrix with different types?

Answer

You cannot; the elements are not different types; all (4) elements of this matrix are lists

all(
is.list(m_list[1,1]), 
is.list(m_list[2,1]), 
is.list(m_list[1,2]), 
is.list(m_list[2,2]))
#[1] TRUE

Question

But I constructed matrix like this: matrix(list('1',2,3,4),2,2), how did this become a matrix of (4) lists, rather than a matrix of (4) characters, or even (4) integers?

Answer

I'm not sure. Even though the documentation says re: the first argument to matrix:

Non-atomic classed R objects are coerced by as.vector and all attributes discarded.

It seems these are identical

identical(as.vector(list('1',2,3,4)), list('1',2,3,4))
#[1] TRUE

Question

But I assign a character ('4') to an element of m_list, how does that work?

m_list[2,2] <-'4'

Answer

It is "coerced", as if you did this:

m_list[2,2] <- as.list('4')

Question

If the elements in m_list are lists, is m_list equivalent to matrix(c(list('1'),list(2),list(3),list(4)),2,2)?

Answer

Yes, these are equivalent:

m_list  <- matrix(list('1',2,3,4),2,2)
m_list2 <- matrix(c(list('1'),list(2),list(3),list(4)),2,2)
identical(m_list, m_list2)
#[1] TRUE

Question

So how can I retrieve the typeof the '1' hidden in m_list[1,1]?

Answer

At least two ways:

typeof(m_list[1,1][[1]])
#[1] "character"

...or, can directly do this (thanks, Frank) (since indexing has this "is applied in turn to the list, the selected component, the selected component of that component, and so on" behavior)...

typeof(m_list[[1,1]])
#[1] "character"

Question

How can I tell the difference between these two

m1 <- matrix(c(list(1), list(2), list(3), list(4)), 2, 2)
m2 <- matrix(1:4, 2, 2)

Answer

If you are using RStudio,

  • m1 is described as List of 4
  • m2 is described as int [1:2, 1:2] 1 2 3 4

..or else, just use typeof(), which for vectors and matrices, identifies the type of their elements... (thanks, Martin)

typeof(m1)
#[1] "list"
typeof(m2)
#[1] "integer"

class can also help distinguish, but you must wrap the matrices in vectors first:

#Without c(...)
class(m1)
#[1] "matrix"
class(m2)
#[1] "matrix"
#With c(...)
class(c(m1))
#[1] "list"
class(c(m2))
#[1] "integer"

...you could tell a subtle difference in the console output; notice how the m2 (containing integers) right-aligns its elements (because numerics are usually right-aligned)...

m1
#     [,1] [,2]
#[1,] 1    3   
#[2,] 2    4   
m2
#     [,1] [,2]
#[1,]    1    3
#[2,]    2    4
like image 110
The Red Pea Avatar answered Sep 30 '22 01:09

The Red Pea


Short-Answer: Matrices in R cannot contain different data types. All data have to or will be transformed into either logical, numerical, character or list.

Matrices always contain the same type. If input data to matrix() have different data types, they will automatically transformed into the same type. Thus, all data will be either logical, numerical, character or list. And here is your case, in your example all elements are being transformed into individual lists.

> myList <- list('1',2,3,4)
> myMatrix <- matrix( myList ,2,2)
> myMatrix
     [,1] [,2]
[1,] "1"  3   
[2,] 2    4 
> typeof(myMatrix)
"list"

If you want to transformed completely your data from a list, you need to unlist the data.

> myList <- list('1',2,3,4)
> myMatrix <- matrix( unlist(myList) ,2,2)
> myMatrix
     [,1] [,2]
[1,] "1"  "3" 
[2,] "2"  "4" 
> typeof(myMatrix)
"character"
like image 30
rafaoc Avatar answered Sep 30 '22 02:09

rafaoc