Ich versuche zu testen, ob alle Elemente eines Vektors gleich sind. Die Lösungen, die ich gefunden habe, scheinen etwas umständlich zu sein, beide beinhalten Überprüfungen length()
.
x <- c(1, 2, 3, 4, 5, 6, 1) # FALSE
y <- rep(2, times = 7) # TRUE
Mit unique()
:
length(unique(x)) == 1
length(unique(y)) == 1
Mit rle()
:
length(rle(x)$values) == 1
length(rle(y)$values) == 1
Eine Lösung, mit der ich einen Toleranzwert für die Bewertung der „Gleichheit“ zwischen Elementen angeben könnte, wäre ideal, um Probleme mit FAQ 7.31 zu vermeiden .
Gibt es eine eingebaute Funktion für die Art des Tests, die ich völlig übersehen habe? identical()
und all.equal()
vergleichen Sie zwei R-Objekte, damit sie hier nicht funktionieren.
Bearbeiten 1
Hier sind einige Benchmarking-Ergebnisse. Verwenden des Codes:
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)
Mit den Ergebnissen:
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
Es sieht also so aus, als wäre diff(range(x)) < .Machine$double.eps ^ 0.5
es am schnellsten.
system.time(for(i in 1:1e4) zero_range(x))
, wox
war aus dem OP. Johns Lösung ist ~ 10x fürx
, ~ 3x schneller füry
und etwas langsamer fürrunif(1e6)
.Warum nicht einfach die Varianz verwenden:
Wenn alle Elemente von
x
gleich sind, erhalten Sie eine Varianz von0
.quelle
length(unique(x))=1
am Ende ist es ungefähr doppelt so schnell, aber esvar
ist knapp, was schön ist.John test: TRUE ; DWin test: TRUE ; zero-range test: TRUE ; variance test: FALSE
Bedeutung, dass alle anderen Tests erkennen, dass die Werte in R identisch sind. Wie kann der Varianztest in diesem Kontext verwendet werden?TRUE
? Bei Johns Antwort prüfen Sie, ob der Unterschied über einem bestimmten Schwellenwert liegt. In Ihrem Fall ist der Unterschied zwischen den beiden Werten sehr gering, was dazu führen kann, dass er unter dem von Ihnen definierten Schwellenwert liegt.Wenn sie alle numerische Werte sind, wenn tol Ihre Toleranz ist, dann ...
ist die Lösung für Ihr Problem.
BEARBEITEN:
Nachdem Sie sich diese und andere Antworten angesehen und einige Dinge verglichen haben, ist das Folgende doppelt so schnell wie die DWin-Antwort.
Dies ist ein bisschen überraschend schneller als
diff(range(x))
dadiff
sollte nicht viel anders sein als-
undabs
mit zwei Zahlen. Das Anfordern des Bereichs sollte das Erhalten des Minimums und Maximums optimieren. Beidediff
undrange
sind primitive Funktionen. Aber das Timing lügt nicht.quelle
Ein anderer in der gleichen Richtung:
quelle
x <- seq(1, 10) / 1e10
Sie können das erste Element verwenden
identical()
undall.equal()
mit allen anderen vergleichen, um den Vergleich effektiv zu vertiefen:Auf diese Weise können Sie nach Bedarf jedes Epsilon hinzufügen
identical()
.quelle
Sie können nur überprüfen
all(v==v[1])
quelle
NA
in Ihrem Vektorx <- c(1,1,NA); all(x == x[1])
Folgendes haben : GibtNA
nicht zurückFALSE
. In solchen Fällenlength(unique(x)) == 1
funktioniert.Da ich immer wieder auf diese Frage zurückkomme, ist hier eine
Rcpp
Lösung, die im Allgemeinen viel schneller ist als jede derR
Lösungen, wenn die Antwort tatsächlich lautetFALSE
(weil sie in dem Moment stoppt, in dem sie auf eine Nichtübereinstimmung stößt) und dieselbe Geschwindigkeit aufweist als schnellste R-Lösung, wenn die Antwort lautetTRUE
. Beispiel: Für den OP-Benchmark wirdsystem.time
mit dieser Funktion genau 0 eingegeben.quelle
fast_equal(c(2,1,3), 1.5)
a == b
,b == c
nicht unbedingt bedeuten ,a == c
wenn Sie Floating - Point - Vergleiche zu tun. Sie können entweder teilen Sie Ihre Präzision durch die Anzahl der Elemente um dieses Problem zu vermeiden, oder den Algorithmus ändern zu berechnenmin
undmax
und die Verwendung dieser als Stoppbedingung.Ich habe speziell dafür eine Funktion geschrieben, mit der nicht nur Elemente in einem Vektor überprüft werden können, sondern auch überprüft werden kann, ob alle Elemente in einer Liste identisch sind . Natürlich kann es auch Zeichenvektoren und alle anderen Arten von Vektoren gut verarbeiten. Es hat auch eine angemessene Fehlerbehandlung.
Versuchen Sie nun einige Beispiele.
quelle
Sie müssen nicht unbedingt min, mean oder max verwenden. Basierend auf Johns Antwort:
quelle
Hier eine Alternative mit dem Min, Max-Trick aber für einen Datenrahmen. Im Beispiel vergleiche ich Spalten, aber der Randparameter von
apply
kann für Zeilen in 1 geändert werden.Wenn
valid == 0
dann alle Elemente gleich sindquelle