It's often said that data.frame inherits from list, which makes sense given many common paradigms for accessing data.frame columns ($, sapply, etc.).
Yet "list" is not among the items returned in the class list of a data.frame object:
dat <- data.frame(x=runif(100),y=runif(100),z=runif(100),g=as.factor(rep(letters[1:10],10)))
> class(dat)
[1] "data.frame"
Unclassing a data.frame shows that it's a list:
> class(unclass(dat))
[1] "list"
And testing it does look like the default method will get called in preference to the list method if there's no data.frame method:
> f <- function(x) UseMethod('f')
> f.default <- function(x) cat("Default")
> f.list <- function(x) cat('List')
> f(dat)
Default
> f.data.frame <- function(x) cat('DF')
> f(dat)
DF
Two questions then:
- Does the failure to have
data.frameformally inherit fromlisthave any advantages from a design perspective? - How do those functions that seem to treat
data.frames as lists know to treat them as lists? From looking atlapplyit looks like it goes to C internal code quite quickly, so perhaps that's it, but my mind's a little blown here.