Как вы проверяете скаляр в R?

Мне интересно идентифицировать числовые скаляры вроде:

doub <- 3.14
intg <- 8L

Я знаю, что они рассматриваются как длина одного вектора. Таким образом, для любого объекта R x, является is.vector(x) && length(x) == 1 правильным способом проверить, является ли x скаляром? length(x) == 1 сам по себе недостаточно, поскольку возвращает true, когда он должен возвращать false, для фрейма данных с одним столбцом или списком с одним элементом.

Есть ли причина, почему такая функция is.scalar не реализована в базе R? По некоторым причинам два случая, которые я мог найти в других функциях, не выполняются для случая фрейма данных, упомянутого ранее, это:

assertthat::is.scalar(data.frame(a = 1:2))
lambda.tools::is.scalar(data.frame(a = 1:2))

Почему результаты этих двух вызовов функций отличаются от моего понимания (и определения) того, как должна работать функция is.scalar?

Ответ 1

Я думаю, что is.atomic соответствует вашим потребностям.

Для чего is.vector, вероятно, несовместимо, см., например:

is.atomic(list(1))
# [1] FALSE

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

На ваших объектах:

is.scalar <- function(x) is.atomic(x) && length(x) == 1L

is.scalar(doub)
# [1] TRUE

is.scalar(intg)
# [1] TRUE

is.scalar(c(doub, intg))
# [1] FALSE

Ответ 2

Основываясь на ответе на @MichaelChirico, есть еще пара вещей, которые должен проверять is.scalar().

Во-первых, комплексные числа обычно не рассматриваются как скаляры (хотя я думаю, что это использование может варьироваться в зависимости от дисциплин).

comp <- 2+3i
is.scalar <- function(x) is.atomic(x) && length(x) == 1L
is.scalar(comp)
# TRUE

поэтому мы должны также проверить комплексные числа. Простой, но наивный способ сделать это - использовать is.complex

is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.complex(x) 
is.scalar(comp)
# FALSE

К сожалению, это не совсем правильно, потому что is.complex просто проверяет, является ли класс "complex". Но действительные числа могут иметь класс = комплекс, если их мнимая компонента равна нулю.

is.complex(2+0i)
# [1] TRUE

Итак, для проверки реальных чисел нам лучше проверить, что мнимая компонента равна нулю, используя Im(x)==0. Итак, это приводит нас к проверке скаляров, которые выглядят так:

is.scalar <- function(x) is.atomic(x) && length(x) == 1L && Im(x)==0

Более тривиально, символы также должны быть устранены

is.scalar("x")
# TRUE
is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.character(x) && Im(x)==0
is.scalar("x")
# FALSE

Обратите внимание, что мы тестируем для is.character(x) до Im(x)==0, чтобы ленивая оценка гарантировала, что функция никогда не пытается найти мнимую составляющую символа, которая выдавала бы ошибку.