人们常说data.frame
继承自list
,考虑到许多访问data.frame列的常见范式($
,sapply
等),这是有道理的。
然而,"list"
不在data.frame
对象的类列表中返回的项之列:
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"
取消分类data.frame
会显示它是一个列表:
> class(unclass(dat))
[1] "list"
并且测试它看起来确实像在没有 data.frame 方法的情况下优先调用默认方法而不是列表方法:
> 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
那么两个问题:
- 从
- 设计的角度来看,无法正式继承
data.frame
list
有什么好处吗? - 那些似乎将
data.frame
视为列表的函数如何知道将它们视为列表? 从lapply
看,它看起来很快就进入了 C 内部代码,所以也许就是这样,但我的想法在这里有点爆炸。
我承认R中的类对我来说也有点困惑。 但我记得曾经读过类似"在 R data.frame 实际上是向量列表"之类的东西。 使用示例中的代码,我们可以验证这一点:
> is.list(dat)
[1] TRUE
?is.list
注意我们也可以使用 [[]]
运算符来访问 dat
的元素(列),这是访问 R 中列表元素的常规方式:
> identical(dat$x, dat[[1]])
[1] TRUE
我们还可以验证每列实际上是一个向量:
> is.vector(dat$x)
[1] TRUE