class() and typeof()

3,021 views
Skip to first unread message

Jane

unread,
Nov 12, 2014, 12:37:56 PM11/12/14
to davi...@googlegroups.com
Dear R-users,

Learning from Hadley's "Advanced R" that typeof() can be used to assess the type of an object; while type is one of the three properties of a vector. "class()" can be used to assess the class attribute of an object. 

"The dimension attribute can be set on lists to make list-matrices or list-arrays". I'm confused about that typeof() and class() give different output given a list-matrices object. Do you have any idea on why typeof() and class() give different output?  Does this difference have any impact on manipulations of this list-matrices? 

Thanks!
Jane

An example (from the book: http://adv-r.had.co.nz/Data-structures.html) is given below:

> l <- list(1:3, "a", TRUE, 1.0)
> dim(l) <- c(2, 2)
> str(l)
List of 4
 $ : int [1:3] 1 2 3
 $ : chr "a"
 $ : logi TRUE
 $ : num 1
 - attr(*, "dim")= int [1:2] 2 2
> class(l)
[1] "matrix"
> typeof(l)
[1] "list"
> is.matrix(l)
[1] TRUE
> is.list(l)
[1] TRUE

Vince S. Buffalo

unread,
Nov 12, 2014, 1:14:40 PM11/12/14
to davi...@googlegroups.com
Setting the dimension of a vector (including lists) makes it either an object with class array or matrix (a matrix if there are two dimensions). For example:

# using your l
>  dim(l) <- c(1, 2, 2)
> class(l)
[1] "array"

The underlying type will always be list, because lists are a fundamental type (like integer, numeric, raw, logical, etc). You can think of them as a type of vector capable of storing elements of heterogeneous types. By changing the dimension, you're just changing the class to matrix or list, just as R's atomic vectors work:

> x <- c(2, 3, 4, 1)
> class(x)
[1] "numeric"
> typeof(x)
[1] "double"
> dim(x) <- c(2, 2)
> class(x)
[1] "matrix"
> typeof(x)
[1] "double"

hope this helps,
Vince





--
Check out our R resources at http://www.noamross.net/davis-r-users-group.html
---
You received this message because you are subscribed to the Google Groups "Davis R Users' Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to davis-rug+...@googlegroups.com.
Visit this group at http://groups.google.com/group/davis-rug.
For more options, visit https://groups.google.com/d/optout.

Jane

unread,
Nov 12, 2014, 9:54:49 PM11/12/14
to davi...@googlegroups.com
Thank you Vince. I seem to understand. "type" is more fundamental than "class". 

The class and type are the same for atomic vectors. Assigning dimensions to an atomic vector changes the class into an array or a matrix depending on the dimensionality. But it does not change the type. 

It seems class is more general. type is more specific and fundamental. "c" and "subset" both have the class "function". But "c" has the type of "builtin", whereas "subset" has the type "closure". 

> class(c)
[1] "function"
> typeof(c)
[1] "builtin"
> class(subset)
[1] "function"
> typeof(subset)
[1] "closure"

Vince S. Buffalo

unread,
Nov 12, 2014, 10:41:25 PM11/12/14
to davi...@googlegroups.com
Hi Jane,
 
I seem to understand. "type" is more fundamental than "class". 

Exactly — my favorite example of this is data.frames and lists. Data.frames differ from matrices because they store columns of different types — unlike matrices, each column can contain a different type. What R data structure can contain objects of different types? Lists! So data.frames are lists:

> l <- list(col1=rnorm(5), col2=sample(c('a', 'b'), 5, replace=TRUE))
> class(l)
[1] "list"
> typeof(l)
[1] "list"
> is.list(l)
[1] TRUE

> d <- data.frame(col1=rnorm(5), col2=sample(c('a', 'b'), 5, replace=TRUE))
> class(d)
[1] "data.frame"
> is.list(d)
[1] TRUE
> typeof(d)
[1] "list"

Data.frames are simply R lists with class "data.frame" (and row.names — these are required). In fact, you can create an R data.frame from a list by just changing the class from "list" to "data.frame" and adding row names:

> class(l) <- "data.frame"
> row.names(l) <- 1:5 # we need row.names
> l
        col1 col2
1 -0.3052572    a
2  1.6734096    a
3  1.1435472    a
4 -1.1576587    a
5 -1.0802156    a
> is.data.frame(l)
[1] TRUE

Hope this helps tie some loose ends! R's data structures are strange at first, but actually quite elegant in the way they all connect with each other.

Vince

Jane

unread,
Nov 12, 2014, 11:14:58 PM11/12/14
to davi...@googlegroups.com
Thank you Vince. This example is very helpful.

It seems the data.frames always get the type of "list", even when all columns in this data.frame are integers. 

> d <- data.frame(col1 = 1:10, col2 = sample(1:2, 5, replace = TRUE))
> class(d)
[1] "data.frame"
> typeof(d)
[1] "list"

However, if convert this data.frame into a matrix, it will has the type of "integer".

BTW, converting a list into a data.frame by changing the class and adding row.names is super useful. I've been struggle with that. Thanks.

Jane
> m <- as.matrix(d)
> class(m)
[1] "matrix"
> typeof(m)
[1] "integer"
Reply all
Reply to author
Forward
0 new messages