Почему класс (data.frame(...)) не показывает наследование списка?

Часто говорят, что 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"

И тестирование похоже на то, что метод по умолчанию будет вызываться в предпочтении перед методом 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Как списки знают, как обращаться с ними как со списками? Смотря на lapply похоже, он довольно быстро переходит к внутреннему коду на C, так что, возможно, это все, но мой ум здесь немного взорван.

1 ответ

Признаюсь, что классы в R меня немного смущают. Но я помню, как однажды прочитал что-то вроде: "В 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
Другие вопросы по тегам