Почему is.vector на кадре данных не возвращает TRUE?

tl; dr. Что, черт возьми, является вектором в R?

Длинная версия:

Много вещей - это вектор в R. Например, число - это числовой вектор длины 1:

is.vector(1)
[1] TRUE

Список также является вектором.

is.vector(list(1))
[1] TRUE

ОК, поэтому список - это вектор. По-видимому, кадр данных является списком.

is.list(data.frame(x=1))
[1] TRUE

Но, (по-видимому, нарушающее транзитивное свойство), кадр данных не является вектором, хотя фрейм данных является списком, а список - вектором. EDIT: это вектор, он просто имеет дополнительные атрибуты, что приводит к такому поведению. См. Принятый ответ ниже.

is.vector(data.frame(x=1))
[1] FALSE

Как это может быть?

3 ответа

Иллюстрируя, что @joran указал, что is.vector возвращает false для вектора, который имеет любые атрибуты, отличные от имен (я этого никогда не знал)...

# 1) Example of when a vector stops being a vector...
> dubious = 7:11
> attributes(dubious)
NULL
> is.vector(dubious)
[1] TRUE
#now assign some additional attributes 
> attributes(dubious) <- list(a = 1:5)
> attributes(dubious)
$a
[1] 1 2 3 4 5
> is.vector(dubious)
[1] FALSE
# 2) Example of how to strip a dataframe of attributes so it looks like a true vector ...
> df = data.frame()
> attributes(df)
$names
character(0)
$row.names
integer(0)
$class
[1] "data.frame"
> attributes(df)[['row.names']] <- NULL
> attributes(df)[['class']] <- NULL
> attributes(df)
$names
character(0)
> is.vector(df)
[1] TRUE


Чтобы ответить на ваш вопрос по-другому, руководство R Internals содержит R восьми встроенных типов векторов: "логический", "цифровой", "character", "list", "complex", "raw", "integer" и "expression".

Чтобы проверить, является ли неатрибутная часть объекта действительно одним из тех векторных типов "под всем этим", вы можете проверить результаты is(), например:

isVector <- function(X) "vector" %in% is(X)
df <- data.frame(a=1:4)
isVector(df)
# [1] TRUE
# Use isVector() to examine a number of other vector and non-vector objects 
la <- structure(list(1:4), mycomment="nothing")
chr <- "word" ## STRSXP
lst <- list(1:4) ## VECSXP
exp <- expression(rnorm(99)) ## EXPRSXP
rw <- raw(44) ## RAWSXP
nm <- as.name("x") ## LANGSXP
pl <- pairlist(b=5:8) ## LISTSXP
sapply(list(df, la, chr, lst, exp, rw, nm, pl), isVector)
# [1] TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE


Не ответ, но вот несколько других интересных вещей, которые определенно заслуживают изучения. Некоторые из них связаны с тем, как объекты хранятся в R.

Один пример:

Если мы установим a matrix одного элемента, этот элемент будет списком, мы получим следующее. Несмотря на то что это список, он может быть сохранен в одном элементе матрицы.

> x <- matrix(list(1:5)) # we already know that list is also a vector
> x
# [,1] 
# [1,] Integer,5

Теперь, если мы привязаем x к кадру данных, его размеры остаются (1, 1)

> y <- as.data.frame(x)
> dim(y)
# [1] 1 1

Теперь, если мы посмотрим на первый элемент y, это столбец фрейма данных,

> y[1]
# V1
# 1 1, 2, 3, 4, 5

Но если мы посмотрим на первый столбец, y, это список

> y[,1]
# [[1]]
# [1] 1 2 3 4 5

который точно совпадает с первой строкой y.

> y[1,]
# [[1]]
# [1] 1 2 3 4 5

Существует много свойств объектов R, которые являются классными для исследования, если у вас есть время.

licensed under cc by-sa 3.0 with attribution.