Próbuję sprawdzić, czy wszystkie elementy wektora są sobie równe. Rozwiązania, które wymyśliłem, wydają się nieco okrężne, oba wymagają sprawdzenia length()
.
x <- c(1, 2, 3, 4, 5, 6, 1) # FALSE
y <- rep(2, times = 7) # TRUE
Z unique()
:
length(unique(x)) == 1
length(unique(y)) == 1
Z rle()
:
length(rle(x)$values) == 1
length(rle(y)$values) == 1
Rozwiązanie, które pozwoliłoby mi uwzględnić wartość tolerancji dla oceny „równości” między elementami, byłoby idealne, aby uniknąć problemów z FAQ 7.31 .
Czy istnieje funkcja wbudowana dla typu testu, którą całkowicie przeoczyłem? identical()
i all.equal()
porównaj dwa obiekty R, więc nie będą tutaj działać.
Edytuj 1
Oto kilka wyników testów porównawczych. Korzystanie z kodu:
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)
Z wynikami:
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
Więc wygląda na to, że diff(range(x)) < .Machine$double.eps ^ 0.5
jest najszybszy.
system.time(for(i in 1:1e4) zero_range(x))
, skądx
pochodziłem z OP. Rozwiązanie Johna jest ~ 10x dlax
, ~ 3x szybsze dlay
i nieco wolniejsze dlarunif(1e6)
.Dlaczego po prostu nie użyć wariancji:
Jeśli wszystkie elementy
x
są równe, otrzymasz wariancję0
.źródło
length(unique(x))=1
kończy się dwukrotnie szybciej, alevar
jest zwięzły, co jest miłe.John test: TRUE ; DWin test: TRUE ; zero-range test: TRUE ; variance test: FALSE
że wszystkie inne testy rozpoznają, że wartości są identyczne w R. Jak można użyć testu wariancji w tym kontekście?TRUE
? W przypadku odpowiedzi Jana sprawdzasz, czy różnica jest powyżej pewnego progu. W twoim przypadku różnica między dwiema wartościami jest bardzo mała, co może prowadzić do tego, że znajdzie się poniżej zdefiniowanego progu.Jeśli wszystkie są wartościami liczbowymi, to jeśli tol jest twoją tolerancją, to ...
jest rozwiązaniem Twojego problemu.
EDYTOWAĆ:
Po przyjrzeniu się temu i innym odpowiedziom oraz przeprowadzeniu testów porównawczych kilku rzeczy, następujące wyniki są dwa razy szybsze niż odpowiedź DWin.
Jest to nieco zaskakujące szybciej niż
diff(range(x))
ponieważdiff
nie powinno być znacznie różni się od-
iabs
dwa numery. Żądanie zakresu powinno zoptymalizować uzyskanie minimum i maksimum. Obiediff
irange
są funkcjami prymitywnymi. Ale czas nie kłamie.źródło
Inny w tym samym stylu:
źródło
x <- seq(1, 10) / 1e10
Możesz użyć
identical()
iall.equal()
porównując pierwszy element ze wszystkimi innymi, skutecznie przeglądając porównanie:W ten sposób możesz dodać dowolny epsilon do
identical()
według potrzeb.źródło
Możesz po prostu sprawdzić
all(v==v[1])
źródło
NA
w swoim wektorze:x <- c(1,1,NA); all(x == x[1])
zwracaNA
, nieFALSE
. W takich przypadkachlength(unique(x)) == 1
działa.Ponieważ w kółko wracam do tego pytania, oto
Rcpp
rozwiązanie, które będzie generalnie znacznie szybsze niż którekolwiek zR
rozwiązań, jeśli odpowiedź brzmi rzeczywiścieFALSE
(ponieważ zatrzyma się w momencie napotkania niedopasowania) i będzie miało tę samą prędkość jako najszybsze rozwiązanie R, jeśli odpowiedź brzmiTRUE
. Na przykład dla benchmarku OPsystem.time
zegar przy użyciu tej funkcji ustawia dokładnie 0.źródło
fast_equal(c(2,1,3), 1.5)
a == b
,b == c
nie musi koniecznie oznaczaća == c
jeśli robisz pływających porównań punktowych. Można też podzielić precyzję przez liczbę elementów, aby uniknąć tego problemu, lub zmodyfikować algorytm do obliczeniamin
imax
i używając które jako warunek zatrzymania.Specjalnie do tego napisałem funkcję, która może sprawdzać nie tylko elementy w wektorze, ale także może sprawdzić, czy wszystkie elementy na liście są identyczne . Oczywiście dobrze radzi sobie z wektorami znakowymi i wszystkimi innymi typami wektorów. Posiada również odpowiednią obsługę błędów.
Teraz wypróbuj kilka przykładów.
źródło
W rzeczywistości nie musisz używać min, mean ani max. Na podstawie odpowiedzi Johna:
źródło
Tutaj alternatywa wykorzystująca sztuczkę min, max, ale dla ramki danych. W przykładzie porównuję kolumny, ale parametr marginesu z
apply
można zmienić na 1 dla wierszy.Jeśli
valid == 0
to wszystkie elementy są takie sameźródło