2016-06-29 2 views
10

Я заинтересован идентификации цифровых скаляры, как:Как проверить скаляр в 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 функция должна работать?

+2

Вы, вероятно, хотите 'is.atomic' вместо' is.vector'. –

+2

В чем разница между этими двумя? – Alex

+0

См. '? Is.atomic':« Обычно называют атомные типы атомных векторов », но обратите внимание, что' is.vector' налагает дополнительные ограничения: объект может быть атомарным, но не вектором (в этом смысле). " – MichaelChirico

ответ

8

Я думаю, 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 
8

здание на answer по @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 так что ленивые вычисления гарантирует, что функция никогда не пытается найти мнимую составляющую персонажа, которая бы породила ошибку.

+0

Итак, почему бы просто не использовать 'is.scalar <- function (x) length (x) == 1L && is.vector (x, mode =" numeric ")'? – Wastl

+1

@Wastl Это зависит от вашей цели и эффективности, за которую вы хотите протестировать, но с использованием вашего определения 'is.scalar (x)' не удастся, например. 'x = 1 + 0i',' x = NA' и 'x = 1; attr (x, 'foo') = 1' – dww

Смежные вопросы