R уникальная команда и табличная команда не согласны - PullRequest
1 голос
/ 15 июня 2019

У меня странная проблема.Для иллюстрации:

a <- c(3.099331946117620972814,
       3.099331946117621860992)

> unique(a)
[1] 3.099331946117620972814 3.099331946117621860992
> table(a)
a
3.09933194611762 
               2

Таким образом, unique() правильно распознает, что цифры отличаются от 15-й цифры.table() однако не считает их разными.

Это может быть ожидаемым поведением, но оно вызывает ошибку в некоторых моих кодах, так как мне нужно, чтобы они оба согласились:

times <- sort(unique(times))
k <- as.numeric(table(times))

разправильно вытаскивает уникальные времена.Предполагается, что k - это число раз, которое происходит каждый раз, но из-за описанной выше проблемы оно не делает это правильно.

У кого-нибудь есть предложение получить уникальную таблицу и согласиться с ней?(или другой обходной путь?)

1 Ответ

3 голосов
/ 15 июня 2019

Попытка использовать unique или table для числа с плавающей запятой концептуально проблематична с точки зрения компьютера.Эта тема тесно связана с R FAQ 7.31 с выдержкой:

Единственными числами, которые могут быть точно представлены в числовом типе R, являются целые числа и дроби, знаменателем которых являетсястепень 2. Все остальные числа внутренне округлены с точностью (как правило) до 53 двоичных цифр.В результате два числа с плавающей запятой не будут надежно равны, если только они не были вычислены одним и тем же алгоритмом, и не всегда даже тогда.Например,

R> a <- sqrt(2)
R> a * a == 2
[1] FALSE
R> a * a - 2
[1] 4.440892e-16
R> print(a * a, digits = 18)
[1] 2.00000000000000044

(Существуют и другие примеры, если вам интересно, я советую вам прочитать больше в этой теме часто задаваемых вопросов.)

В связи с этим я предлагаю вам принять решение отребуемой точности, а затем используйте именно эти цифры при поиске уникальности.Используя ваши номера, вы можете вызвать проблему с помощью formatsprintf):

a <- c(3.099331946117620972814,
       3.099331946117621860992)

table(format(a, digits = 15))
# 3.09933194611762 
#                2 
table(format(a, digits = 16))
# 3.099331946117621 3.099331946117622 
#                 1                 1 

unique(format(a, digits = 15))
# [1] "3.09933194611762"
unique(format(a, digits = 16))
# [1] "3.099331946117621" "3.099331946117622"

Для любопытных причина того, что unique и table различны, коренится где-тоtable использует factor, что, в свою очередь, использует as.character(y).Если вы сделаете as.character(a), то произойдет произвольное снижение точности до 14 цифр:

as.character(a)
# [1] "3.09933194611762" "3.09933194611762"

Таким образом, чтобы ответить на вопрос, который вы задали : unique и table отличаются, потому чтоtable в конечном итоге использует as.character, который по умолчанию усекается до 14 цифр.(Поскольку это примитив, вам понадобится перейти к низкоуровневому источнику, чтобы выяснить это.)

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

...