2013-10-26 34 views
8

人們常說,data.frame繼承自list,這對於訪問data.frame列($,sapply等)有許多常見的範例是有意義的。爲什麼class(data.frame(...))不顯示列表繼承?

然而"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" 

Unclassing一個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 

兩個問題,那麼:

  1. 是否未能有data.frame正式繼承list具有從設計的角度來看有什麼優勢?
  2. 那些似乎將data.frame s作爲列表的函數如何知道將它們視爲列表?從lapply看起來它很快就會轉到C語言的內部代碼,所以也許就是這樣,但是我的想法在這裏有一點點。
+4

我猜它歸結爲工作效率。 S3方法調度是昂貴的,並且列表是R中非常基本的數據結構。因此,它們在C級處理。例如,即使'is.list'也是一個原語(與「is.data.frame」相反)。 – Roland

+4

誰從'list'中說'data.frame' _inherits_是錯誤的。它們可能意味着data.frames被實現爲具有特定屬性和特徵的列表。如果'X'不是一個向量,或者'is.object'是'TRUE'(基本上是有'class'屬性的話),'lapply'會調用'as.list'。 'as.list'與'data.frame'方法是通用的。 –

+4

我在http://adv-r.had.co.nz/OO-essentials.html#method-dispatch中對此進行了一些討論。 @JoshuaUlrich我認爲說data.frame從列表繼承是不合理的,但它很複雜,因爲列表和數據框不屬於同一個對象系統。 – hadley

回答

1

我承認R中的類對我來說也有點困惑。但是我記得曾經閱讀過類似「In R data.frames實際上是向量列表」的東西。從您的示例使用代碼,我們就可以驗證這一點:

> is.list(dat) 
[1] TRUE 
?is.list 

請注意,我們也可以使用[[]]運營商訪問的dat元素(列),這是訪問R中列出的元素以正常的方式:

> identical(dat$x, dat[[1]]) 
[1] TRUE 

我們也可以驗證每個列實際上是一個向量:

> is.vector(dat$x) 
[1] TRUE 
相關問題