Подтвердить что ты не робот

Как (x, 'double') и as.double(x) несовместимы

x <- 1:10
str(x)
# int [1:10] 1 2 3 4 5 6 7 8 9 10
str(as.double(x))
# num [1:10] 1 2 3 4 5 6 7 8 9 10 
str(as(x, 'double'))
# int [1:10] 1 2 3 4 5 6 7 8 9 10

Я был бы удивлен, если бы была ошибка в R с чем-то таким простым, как преобразование типов. Есть ли причина для этой несогласованности?

4b9b3361

Ответ 1

as предназначен для принудительного ввода в новый class, а double технически не является class, а скорее a storage.mode.

y <- x
storage.mode(y) <- "double"
identical(x,y)
[1] FALSE
> identical(as.double(x),y)
[1] TRUE

Аргумент "double" обрабатывается как частный случай с помощью as и будет пытаться принуждать к классу numeric, который уже наследует класс integer, поэтому изменений нет.

is.numeric(x)
[1] TRUE

Не так быстро...

В то время как вышеизложенное имело смысл, есть еще одна путаница. Из ?double:

Это историческая аномалия, что R имеет два имени для своей плавающей точки векторы, двойные и числовые (и ранее были реальные).

double - это имя типа. numeric - это название режима и также неявного класса. В качестве формального класса S4 используйте "числовые".

Потенциальная путаница заключается в том, что R использовал режим "числовой" для обозначения 'Double или integer, что противоречит использованию S4. таким образом is.numeric проверяет режим, а не класс, но as.numeric(который идентичный as.double) принуждает к классу.

Поэтому as должен действительно изменить x в соответствии с документацией... Я буду исследовать далее.

Участок толще, чем взбитые сливки и суп из кукурузной муки...

Хорошо, если вы debug as, вы узнаете, что в конечном итоге происходит то, что создается следующий метод, а не с использованием подписи c ( "ANY", "numeric" ) для coerce generic, которая вызовет as.numeric:

function (from, strict = TRUE) 
if (strict) {
    class(from) <- "numeric"
    from
} else from

Итак, class<- вызывается на x, и это означает, что R_set_class вызывается из coerce.c. Я считаю, что следующая часть функции определяет поведение:

...
else if(!strcmp("numeric", valueString)) {
    setAttrib(obj, R_ClassSymbol, R_NilValue);
    if(IS_S4_OBJECT(obj)) /* NULL class is only valid for S3 objects */
      do_unsetS4(obj, value);
    switch(TYPEOF(obj)) {
    case INTSXP: case REALSXP: break;
    default: PROTECT(obj = coerceVector(obj, REALSXP));
    nProtect++;
    }
...

Обратите внимание на оператор switch: он вырывается без принуждения в случае целых чисел и реальных значений.

Ошибка или нет?

Является ли это ошибкой, зависит от вашей точки зрения. Целые числа в одном смысле, как подтверждено is.numeric(x) возвращением TRUE, но, строго говоря, они не являются числовым классом. С другой стороны, поскольку целые числа получают возможность автоматически удваиваться при переполнении, можно концептуально их рассматривать как одно и то же. Существуют два основных отличия: i) Целые числа требуют меньше места для хранения - это может быть значительным для больших векторов, и, ii) при взаимодействии с внешним кодом, который имеет более высокие затраты на перераспределение дисциплины, может вступить в игру.

Ответ 2

как (х, "двойной" ): Методы предварительно определены для принуждения любого объекта к одному из базовых типов данных. Например, поскольку (x, "numeric" ) использует существующую функцию as.numeric. Эти встроенные методы могут быть перечислены showMethods ( "coerce" ). Эти функции управляют отношениями, которые позволяют принуждать объект к заданный класс.

as.double(х): as.double - это общая функция. Он идентичен номеру. Методы должны возвращать объект базового типа "double". as.double создает, принуждает или тестирует вектор с двойной точностью.