Menu

Типы данных в R: numeric, character, logical (typeof и class)

Атомарные типы данных в R — double, integer, character, logical — а также чем отличаются typeof() и class() и как работают преобразование и приведение типов.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Типы данных в R

У каждого значения в R есть один из небольшого набора атомарных типов. Четыре из них делают почти всю работу:

  • double — десятичные числа: 3.14, -2, 1e6. Именно это R подразумевает под «numeric», и это тип по умолчанию для любого набранного вами числа.
  • integer — целые числа, хранящиеся точно, записываются с суффиксом L: 42L.
  • character — текст в кавычках: "hello".
  • logical — два значения истинности TRUE и FALSE (плюс NA, пропущенное значение — см. пропущенные значения).

Есть ещё complex (2 + 3i) для редких задач цифровой обработки сигналов; можно годами обходиться без него. typeof() сообщает, какой тип у значения:

Обратите внимание на первую строку: обычное число — это double, даже если выглядит целым. typeof(42) даёт "double"; целое — только 42L. В повседневном анализе разница почти не важна — R преобразует их молча, — но она объясняет много иначе непонятного вывода typeof().

typeof() против class(): почему они расходятся

В R есть две функции, каждая из которых будто отвечает на вопрос «что это?», но отвечают они на слегка разные вопросы.

  • typeof() сообщает тип хранения: как значение лежит в памяти.
  • class() сообщает поведенческий тип: ярлык, по которому диспетчеризация методов R решает, какой, скажем, print или summary запустить.

Для простых значений ответы различаются только словами:

typeof() говорит double (хранение), class() говорит numeric (поведение). Для структур разрыв шире:

Матрица хранится как обычный целочисленный вектор, но ведёт себя как матрица — именно class() заставляет R печатать её сеткой. То же расхождение проявляется у датафреймов (typeof говорит "list", class"data.frame") и у дат (typeof говорит "double", class"Date").

Практическое правило: пользуйтесь class(), когда хотите узнать, что это такое в обыденном смысле, и typeof(), когда отлаживаете то, что R делает под капотом.

Проверка типов через is.*()

У каждого типа есть парный предикат, возвращающий TRUE или FALSE, — удобно внутри функций, которым нужно проверить свои входные данные:

Одна ловушка, о которой стоит знать: is.numeric() даёт TRUE и для double, и для integer (это всё числа), а вот is.integer() проверяет хранение, поэтому для обычной 42 он FALSE:

Если вас когда-нибудь удивляло, что is.integer(7) равно FALSE для числа, которое в математическом смысле очевидно целое, — вот почему. 7 — это double; 7L — integer.

Преобразование типов через as.*()

Явное преобразование выполняется семейством as.* — по одной функции на целевой тип:

Два поведения стоит запомнить. as.integer() усекает в сторону нуля, а не округляет — 7.9 становится 7. И когда преобразование бессмысленно, R не бросает ошибку; он возвращает NA и выдаёт предупреждение:

Запустите это — и увидите NA плюс предупреждение «NAs introduced by coercion». Это по-настоящему полезно — преобразуйте целый столбец грязного текста в числа, и неразбираемые записи станут NA вместо падения скрипта, — но это же означает, что тихий NA может просочиться в ваши данные. Когда преобразование важно, проверяйте после него появление новых NA.

Логические значения преобразуются в числа и обратно так, как и хотелось бы: as.numeric(TRUE) это 1, as.logical(0) это FALSE. Поэтому sum() от логического вектора считает количество TRUE:

Неявное приведение: правило одного типа для векторов

Атомарный вектор в R может хранить только один тип. Объедините смешанные значения через c() — и R молча повысит всё до самого гибкого из присутствующих типов по фиксированной лестнице:

logical → integer → double → character

Логические стали 1 и 0, целые стали double, а в последней строке всё стало текстом — character всегда побеждает, потому что любое значение можно записать строкой. Убедиться можно через typeof():

Приведение типов — источник номер один багов «почему мой столбец текстовый?»: одна затесавшаяся строка "N/A" в столбце чисел приводит весь вектор к character. Когда так случилось, сначала исправьте виновное значение, а затем преобразуйте обратно через as.numeric().

Что вы уносите с собой

  • Четыре рабочих типа: double («numeric»), integer (42L), character, logical.
  • typeof() = как хранится; class() = как ведёт себя. 3.14 — это double, ведущий себя как numeric.
  • Проверяйте через is.numeric() и родственные функции; преобразуйте через as.numeric() и родственные — неудачные преобразования дают NA с предупреждением, а не ошибку.
  • Векторы хранят только один тип; смешивание приводит по цепочке logical → integer → double → character.

Дальше: подробнее о числовых типах — округление, математические функции и сюрпризы плавающей точки, общие для всех языков.

Часто задаваемые вопросы

Какие базовые типы данных есть в R?

Атомарные типы — это double (десятичные числа, то, что R называет «numeric»), integer (целые числа с суффиксом L, например 42L), character (текст в кавычках), logical (TRUE/FALSE) и редко используемый complex. Всё более крупное — векторы, датафреймы, списки — строится из них.

В чём разница между typeof() и class() в R?

typeof() сообщает, как значение хранится в памяти (его низкоуровневый тип); class() сообщает, как значение себя ведёт, и это управляет тем, какие методы вызывает R. Для обычного десятичного числа они расходятся в формулировке — typeof(3.14) даёт "double", а class(3.14) даёт "numeric", — а для структур вроде датафреймов typeof() говорит "list", тогда как class() говорит "data.frame".

Как преобразовать типы в R?

Используйте семейство as.*: as.numeric("3.5") даёт 3.5, as.character(42) даёт "42", as.integer(7.9) усекает до 7. Когда преобразование невозможно, R возвращает NA и выдаёт предупреждение, а не ошибку — as.numeric("abc") это NA.

Что такое приведение типов в R?

Когда вы объединяете разные типы в одном векторе, R молча преобразует всё к самому гибкому типу в порядке logical → integer → double → character. Так c(1, 2, "three") становится символьным вектором: "1" "2" "three".

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ