Я пытаюсь проверить, все ли элементы вектора равны друг другу. Решения, которые я придумал, кажутся несколько окольными, оба предполагают проверку length()
.
x <- c(1, 2, 3, 4, 5, 6, 1) # FALSE
y <- rep(2, times = 7) # TRUE
С unique()
:
length(unique(x)) == 1
length(unique(y)) == 1
С rle()
:
length(rle(x)$values) == 1
length(rle(y)$values) == 1
Решение, которое позволило бы мне включить значение допуска для оценки «равенства» между элементами, было бы идеальным, чтобы избежать проблем с FAQ 7.31 .
Есть ли встроенная функция для типа теста, который я полностью упустил из виду? identical()
и all.equal()
сравните два объекта R, поэтому они не будут работать здесь.
Редактировать 1
Вот некоторые результаты тестов. Используя код:
library(rbenchmark)
John <- function() all( abs(x - mean(x)) < .Machine$double.eps ^ 0.5 )
DWin <- function() {diff(range(x)) < .Machine$double.eps ^ 0.5}
zero_range <- function() {
if (length(x) == 1) return(TRUE)
x <- range(x) / mean(x)
isTRUE(all.equal(x[1], x[2], tolerance = .Machine$double.eps ^ 0.5))
}
x <- runif(500000);
benchmark(John(), DWin(), zero_range(),
columns=c("test", "replications", "elapsed", "relative"),
order="relative", replications = 10000)
С результатами:
test replications elapsed relative
2 DWin() 10000 109.415 1.000000
3 zero_range() 10000 126.912 1.159914
1 John() 10000 208.463 1.905251
Похоже, diff(range(x)) < .Machine$double.eps ^ 0.5
это самый быстрый.
system.time(for(i in 1:1e4) zero_range(x))
, откудаx
был из ОП. Решение Джона примерно в 10 раз дляx
, в ~ 3 раза быстрееy
и немного медленнее дляrunif(1e6)
.Почему бы просто не использовать дисперсию:
Если все элементы
x
равны, вы получите дисперсию0
.источник
length(unique(x))=1
оказывается примерно в два раза быстрее, ноvar
лаконичен, что приятно.John test: TRUE ; DWin test: TRUE ; zero-range test: TRUE ; variance test: FALSE
что все остальные тесты распознают, что значения идентичны в R. Как можно использовать тест дисперсии в этом контексте?TRUE
? В случае ответа Джона вы проверяете, превышает ли разница определенный порог. В вашем случае разница между двумя значениями очень мала, что может привести к тому, что она окажется ниже установленного вами порога.Если это все числовые значения, то если tol - ваша терпимость, тогда ...
это решение вашей проблемы.
РЕДАКТИРОВАТЬ:
Посмотрев на этот и другие ответы, а также протестировав несколько вещей, следующее получается более чем в два раза быстрее, чем ответ DWin.
Это немного на удивление быстрее, чем,
diff(range(x))
посколькуdiff
не должно сильно отличаться от-
иabs
с двумя числами. Запрос диапазона должен оптимизировать получение минимума и максимума. Обаdiff
иrange
являются примитивными функциями. Но время не врет.источник
Другой в том же духе:
источник
x <- seq(1, 10) / 1e10
Вы можете просто проверить
all(v==v[1])
источник
NA
в вашем векторе нет:x <- c(1,1,NA); all(x == x[1])
returnNA
, notFALSE
. В таких случаяхlength(unique(x)) == 1
работает.Вы можете использовать
identical()
иall.equal()
, сравнивая первый элемент со всеми остальными, эффективно проводя сравнение:Таким образом, вы можете добавить любой эпсилон по
identical()
мере необходимости.источник
Поскольку я продолжаю возвращаться к этому вопросу снова и снова, вот
Rcpp
решение, которое, как правило, будет намного быстрее, чем любое изR
решений, если ответ будет на самом делеFALSE
(потому что он остановится в момент обнаружения несоответствия) и будет иметь ту же скорость как самое быстрое решение R, если ответ -TRUE
. Например, для теста OPsystem.time
с помощью этой функции частота равна 0.источник
fast_equal(c(2,1,3), 1.5)
a == b
,b == c
не обязательно означает , чтоa == c
если вы делаете сравнения с плавающей точкой. Вы можете либо разделить точность по количеству элементов , чтобы избежать этой проблемы, или изменить алгоритм для вычисленияmin
иmax
и использовать это как условие остановки.Я написал специально для этого функцию, которая может проверять не только элементы в векторе, но и проверять идентичность всех элементов в списке . Конечно, он также хорошо обрабатывает символьные векторы и все другие типы векторов. Он также имеет соответствующую обработку ошибок.
А теперь попробуйте несколько примеров.
источник
На самом деле вам не нужно использовать минимальное, среднее или максимальное значение. На основании ответа Джона:
источник
Здесь альтернатива с использованием трюка min, max, но для кадра данных. В этом примере я сравниваю столбцы, но параметр поля from
apply
можно изменить на 1 для строк.Если
valid == 0
тогда все элементы одинаковыеисточник