В чем разница между режимом и классом в R?

Я изучаю R (я начал только на этой неделе), и я боролся с концепциями typeof, mode, storage.mode и класса. Я искал вверх и вниз (официальная документация R, StackOverflow, Google и т.д.), И я не смог найти ясного объяснения различий между ними. (Несколько qaru.site/info/455977/... и CrossValidated ответы на самом деле не помогли мне разозлить.) Наконец (надеюсь), я думаю, что понимаю, и поэтому мой вопрос заключается в проверке правильности моего понимания.

mode vs storage.mode: mode и storage.mode - это в основном то же самое, за исключением крошечного разница в том, как обрабатывается "одиночный" тип данных.

mode vs typeof: Очень похоже, за исключением нескольких различий, наиболее заметно, что оба (typeof "integer" и "double" ) = (режим "числовой" ); и оба (typeof "special" и "builtin" = (режим "функция" ).

class: Класс основан на объектно-ориентированной иерархии классов. Мне сложно найти это графически, но лучшее, что я смог найти, это диаграмма:

rpy2 robjects package

(Если кто-то может указать мне более точную иерархию R-класса, я его заменим.)

Хотя имена классов точно не соответствуют результатам функции R class(), я считаю, что иерархия в основном точна. Я понимаю, что "класс" объекта, т.е. Результат функции класса() - это корневой класс в иерархии. Так, например, "Вектор" не является корневым классом, поэтому он никогда не появляется в результате функции класса(). Корневой класс может быть скорее "StrVector" ( "character" ) или "BoolVector" ( "логический" ). Напротив, "Матрица" сама по себе является корневым классом; следовательно, его класс является "матрицей".

По-видимому, R поддерживает множественное наследование, поэтому некоторые объекты могут иметь более одного класса.

typeof/mode/storage.mode vs class: Это то, что для меня было самым сложным для понимания. Теперь я понимаю следующее: typeof/mode/storage.mode(который я буду называть далее просто "mode" ) - это в основном самый сложный тип данных, который объект R может удерживать как одно из своих значений, Так, например, поскольку матрицы, массивы и векторы могут содержать только один векторный тип данных, их режим (то есть самый сложный тип данных, который они могут удерживать) обычно является числовым, символьным или логическим, хотя их класс (их позиция в классе иерархия) - это нечто совершенно другое.

Если это становится наиболее интересным (то есть запутанным), это объекты, подобные спискам. Режим "списка" означает, что каждое значение в объекте может быть списком (то есть объектом, который может содержать различные типы данных). Таким образом, независимо от того, является ли сам класс "списком", существует несколько объектов (например, кадры данных), которые могут содержать различные значения, и поэтому этот режим является "списком", даже если их класс является чем-то другим.

Итак, в общем, я понимаю:

  • typeof/mode/storage.mode(почти то же самое) - это в основном самый сложный тип данных, который объект R может удерживать как одно из его значений; в то время как

  • class - объектная объектно-ориентированная классификация в соответствии с иерархией классов R.

Насколько я понимаю? Если нет, может кто-то, пожалуйста, дать более точное объяснение?

Ответ 1

"Режим" - это взаимоисключающая классификация объектов в соответствии с их основная структура. "Атомные" режимы являются числовыми, сложными, характер и логика. Рекурсивные объекты имеют такие режимы, как "список" или "функция" или несколько других. Объект имеет один и только один режим.

'class' - это свойство, назначенное объекту, которое определяет, насколько функции работают с ним. Это не взаимоисключающий классификация. Если объекту не присвоен конкретный класс, такой как простой числовой вектор, его класс обычно совпадает с его режимом, по договоренности.

Изменение режима объекта часто называют "принуждением". Режим работы объект может меняться без необходимости изменения класса. например,

> x <- 1:16
> mode(x)
[1] "numeric"
> dim(x) <- c(4,4)
> mode(x)
[1] "numeric"
> class(x)
[1] "matrix"
> is.numeric(x)
[1] TRUE
> mode(x) <- "character"
> mode(x)
[1] "character"
> class(x)
[1] "matrix"

Однако:

> x <- factor(x)
> class(x)
[1] "factor"
> mode(x)
[1] "numeric"

На этом этапе, хотя x снова имеет числовой режим, его новый класс, factor запрещает его использование в арифметических операциях.

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

Ответ 2

Я надеюсь, что следующие примеры полезны. В частности, взгляните на последние два примера.

x <- 1L
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- 1
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- letters
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- TRUE
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- cars
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- cars[1]
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- cars[[1]]
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- matrix(cars)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- new.env()
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- expression(1 + 1)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- quote(y <- 1 + 1)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

x <- ls
print(c(class(x), mode(x), storage.mode(x), typeof(x)))

Результаты:

[1] "integer"      "numeric"      "integer"      "integer"
[1] "numeric"      "numeric"      "double"       "double" 
[1] "character"    "character"    "character"    "character"
[1] "logical"      "logical"      "logical"      "logical"
[1] "data.frame"   "list"         "list"         "list"      
[1] "data.frame"   "list"         "list"         "list"      
[1] "numeric"      "numeric"      "double"       "double" 
[1] "matrix"       "list"         "list"         "list"  
[1] "environment"  "environment"  "environment"  "environment"
[1] "expression"   "expression"   "expression"   "expression"
[1] "<-"           "call"         "language"     "language"
[1] "function"     "function"     "function"     "closure" 

В последнем примере показан случай, когда typeof()! = storage.mode().