Неожиданное поведение таблицы функций со значениями "NaN"
Недавно я столкнулся с поведением в функции table
, которая не была тем, что я ожидал:
Например, возьмем следующий вектор:
ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA)
Если я проверяю значения NA
в моем векторе, "NaN"
не считается одним (как ожидалось):
is.na(ex_vec)
# [1] FALSE FALSE FALSE FALSE FALSE TRUE
Но если я попытался получить разные значения частот:
table(ex_vec)
#ex_vec
#Nan Non Oui
# 1 2 1
"NaN"
не отображается в таблице.
Однако, если я "спрошу" table
, чтобы показать значения NA
, я получаю следующее:
table(ex_vec, useNA="ifany")
#ex_vec
# Nan NaN Non Oui <NA>
# 1 1 2 1 1
Итак, символьные строки "NaN"
рассматриваются как значение NA
внутри вызова table
, а обрабатываются в выводе как значение не NA
.
Я знаю (было бы лучше и) я мог бы решить свою проблему, преобразовывая свой вектор в factor
, но, тем не менее, мне бы очень хотелось узнать, что происходит здесь. У кого-нибудь есть идея?
Ответы
Ответ 1
Когда factor
соответствует уровням для вектора, он преобразует свой список exclude
в тот же тип, что и входной вектор:
exclude <- as.vector(exclude, typeof(x))
поэтому, если ваш список исключений имеет NaN
, и ваш вектор является символом, это происходит:
as.vector(exclude, typeof(letters))
[1] NA "NaN"
Боже мой. Теперь будут исключены реальные строки "NaN"
.
Чтобы исправить, используйте exclude=NA
в table
(и factor
, если вы делаете факторы, которые могут повлиять на это).
Мне нравится это в документах для factor
:
There are some anomalies associated with factors that have ‘NA’ as
a level. It is suggested to use them sparingly, e.g., only for
tabulation purposes.
Успокаивает...
Ответ 2
Первой идеей, на мой взгляд, было взглянуть на определение table
, которое начинается с:
> table
function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no",
"ifany", "always"), dnn = list.names(...), deparse.level = 1)
{
Звучит логично, по умолчанию таблица исключает NA
и NaN
.
Копаем в код таблицы, мы видим, что если x
не является фактором, он принуждает его к фактору (ничего нового здесь, он сказал в документе).
else {
a <- factor(a, exclude = exclude)
Я не нашел ничего другого, что могло повлиять на вход для принудительного вложения "NaN"
в значения NA
.
Итак, посмотрим на фактор, чтобы понять причину:
> factor
function (x = character(), levels, labels = levels, exclude = NA,
ordered = is.ordered(x), nmax = NA)
{
[...] # Snipped for brievety
exclude <- as.vector(exclude, typeof(x))
x <- as.character(x)
levels <- levels[is.na(match(levels, exclude))] # defined in the snipped part above, is the sorted unique values of input vector, coerced to char.
f <- match(x, levels)
[...]
f
}
Здесь мы получили его, параметр exclude, даже будучи NA
значениями, принуждаются к символьному вектору.
Итак, что происходит:
> ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA)
> excludes<-c(NA,NaN)
> as.vector(excludes,"character")
[1] NA "NaN"
> match(ex_vec,as.vector(excludes,"character"))
[1] NA NA NA NA 2 1
Мы сопоставляем символ "NaN" как вектор исключения, который был принужден к символу перед сравнением.