Возможная ошибка в R all.equal

Я столкнулся с некоторым странным поведением в функции all.equal R. По сути, я создаю два одинаковых кадра данных по-разному, а затем вызываю функцию all.equal (также проверяя данные и атрибуты).

Код для воспроизведения поведения выглядит следующим образом:

var.a <- data.frame(cbind(as.integer(c(1,5,9)), as.integer(c(1,5,9))))
colnames(var.a) <- c("C1", "C2")
rownames(var.a) <- c("1","5","9")

var.b <- data.frame(matrix(NA, nrow = 10, ncol = 2))
var.b[, 1] <- 1:10
var.b[, 2] <- 1:10
colnames(var.b) <- c("C1", "C2")
var.b <- var.b[seq(1, nrow(var.b), 4), ]

all.equal(var.a, var.b)

Это ошибка или я просто что-то упускаю? Я провел некоторую отладку функции all.equall, и оказалось, что проблема заключается в именах строк data.frames (когда они были символом, а в другой раз - числовым вектором). Ответ функции all.equall:

[1] "Атрибуты: ‹ Компонент 2: Режимы: символьный, числовой >"
[2] "Атрибуты: ‹ Компонент 2: цель – символ, текущий – число >"

Однако,

typeof(имена строк(var.a)) == typeof(имена строк(var.b))

возвращает TRUE, что меня смущает.

P.S.: Структура объектов одинакова:

> str(var.a)
'data.frame':   3 obs. of  2 variables:
$ C1: int  1 5 9
$ C2: int  1 5 9
> str(var.b)
'data.frame':   3 obs. of  2 variables:
$ C1: int  1 5 9
$ C2: int  1 5 9

Я был бы признателен, если бы кто-то мог пролить свет на это.


r
person Igor    schedule 17.09.2012    source источник


Ответы (3)


(Мне не совсем понятно, какую ошибку, как вы думаете, вы нашли. Фреймы данных создавались по-разному.) В структурах var.a и var.b есть два различия: режим элементов в столбцы: numeric в 'var.a' и integer в 'var.b'; и режим имен строк: integer для 'var.a' и character для 'var.b':

> dput(var.b)
structure(list(C1 = c(1L, 5L, 9L), C2 = c(1L, 5L, 9L)), .Names = c("C1", 
"C2"), row.names = c(1L, 5L, 9L), class = "data.frame")
> dput(var.a)
structure(list(C1 = c(1, 5, 9), C2 = c(1, 5, 9)), .Names = c("C1", 
"C2"), row.names = c("1", "5", "9"), class = "data.frame")

> mode(attr(var.b, "row.names"))
[1] "numeric"
> storage.mode(attr(var.b, "row.names"))
[1] "integer"
> mode(attr(var.a, "row.names"))
[1] "character"

Добавлено примечание: если вы хотите проверить числовое равенство, вы должны использовать переключатель «check.attributes»:

> all.equal(var.a, var.b, check.attributes=FALSE)
[1] TRUE

Если вы посмотрите на var.b с dput, вы увидите, что имена строк числовые:

> dput(var.b)
structure(list(C1 = c(1L, 5L, 9L), C2 = c(1L, 5L, 9L)), .Names = c("C1", 
"C2"), row.names = c(1L, 5L, 9L), class = "data.frame")
person IRTFM    schedule 17.09.2012
comment
+10 -- Справка для row.names очень понятна при изменении символа/целого числа. - person mnel; 17.09.2012
comment
Вот и все. Спасибо. Помощь объясняет это хорошо, хотя это не самое интуитивно понятное. - person Igor; 17.09.2012

Однако,

typeof(имена строк(var.a)) == typeof(имена строк(var.b))

возвращает TRUE, что меня смущает.

В дополнение к ответу с наибольшим количеством голосов обратите внимание, что атрибуты хранятся как "character" для var.a и как "numeric" для var.b:

> attr(var.a, "row.names")
[1] "1" "5" "9"
> attr(var.b, "row.names")
[1] 1 5 9

Принимая во внимание, что функция rownames() принудит свое выходное значение к "character":

> rownames(var.a)
[1] "1" "5" "9"
> rownames(var.b)
[1] "1" "5" "9"

Вот почему вы получаете TRUE в приведенной выше команде. Согласно ?rownames:

Для фрейма данных значение для rownames должно быть вектором символов не дублирующих и не пропущенных имен (это принудительно), а для colnames вектором символов (предпочтительно) уникальных синтаксически допустимых имен. В обоих случаях значение будет приведено к as.character, а установка colnames преобразует имена строк в символы.

Более уместной проверкой будет:

> typeof(attr(var.a, "row.names")) == typeof(attr(var.b, "row.names"))
[1] FALSE

При этом я считаю, что all.equal() сообщения в лучшем случае загадочны...

person landroni    schedule 01.09.2015

Один имеет числовой режим, а другой - целочисленный режим. Вы можете увидеть это с помощью:

str(var.a); str(var.b)


> str(var.a); str(var.b)
'data.frame':   3 obs. of  2 variables:
 $ C1: num  1 5 9
 $ C2: num  1 5 9
'data.frame':   3 obs. of  2 variables:
 $ C1: int  1 5 9
 $ C2: int  1 5 9
person Tyler Rinker    schedule 17.09.2012
comment
Это верно, но это не причина неудач all.equal. Я забыл включить это, воспроизводя проблему и делая ее более осознанной. Теперь он включен в исходный вопрос. - person Igor; 17.09.2012