Estoy tratando de probar si todos los elementos de un vector son iguales entre sí. Las soluciones que he encontrado parecen algo indirectas, y ambas implican verificación length().
x <- c(1, 2, 3, 4, 5, 6, 1) # FALSE
y <- rep(2, times = 7) # TRUE
Con unique():
length(unique(x)) == 1
length(unique(y)) == 1
Con rle():
length(rle(x)$values) == 1
length(rle(y)$values) == 1
Una solución que me permitiera incluir un valor de tolerancia para evaluar la 'igualdad' entre elementos sería ideal para evitar problemas de la pregunta frecuente 7.31 .
¿Existe una función incorporada para el tipo de prueba que he pasado por alto por completo? identical()y all.equal()compare dos objetos R, para que no funcionen aquí.
Editar 1
A continuación, se muestran algunos resultados de evaluación comparativa. Usando el código:
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)
Con los resultados:
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
Entonces parece que diff(range(x)) < .Machine$double.eps ^ 0.5es el más rápido.

system.time(for(i in 1:1e4) zero_range(x)), de dóndexera el OP. La solución de John es ~ 10x parax, ~ 3x más rápida parayy ligeramente más lenta pararunif(1e6).¿Por qué no simplemente usar la variación?
Si todos los elementos de
xson iguales, obtendrá una variación de0.fuente
length(unique(x))=1termina siendo aproximadamente el doble de rápido, perovares conciso, lo cual es bueno.John test: TRUE ; DWin test: TRUE ; zero-range test: TRUE ; variance test: FALSEque todas las demás pruebas reconocen que los valores son idénticos en R. ¿Cómo se puede usar la prueba de varianza en ese contexto?TRUE? En el caso de la respuesta de John, verifica si la diferencia está por encima de cierto umbral. En su caso, la diferencia entre los 2 valores es muy baja, lo que podría hacer que esté por debajo del umbral que definió.Si todos son valores numéricos, entonces si tol es su tolerancia, entonces ...
es la solución a tu problema.
EDITAR:
Después de ver esta y otras respuestas, y comparar algunas cosas, lo siguiente resulta dos veces más rápido que la respuesta de DWin.
Esto es un poco sorprendentemente más rápido que
diff(range(x))yadiffque no debería ser muy diferente de-yabscon dos números. Solicitar el rango debe optimizar obteniendo el mínimo y el máximo. Ambosdiffyrangeson funciones primitivas. Pero el momento no miente.fuente
Otro en la misma línea:
fuente
x <- seq(1, 10) / 1e10Puede usar
identical()yall.equal()comparando el primer elemento con todos los demás, barriendo efectivamente la comparación a través de:De esa manera, puede agregar cualquier épsilon
identical()según sea necesario.fuente
Solo puedes comprobar
all(v==v[1])fuente
NAen su vector:x <- c(1,1,NA); all(x == x[1])devuelveNA, noFALSE. En tales casoslength(unique(x)) == 1funciona.Como sigo volviendo a esta pregunta una y otra vez, aquí hay una
Rcppsolución que generalmente será mucho más rápida que cualquiera de lasRsoluciones si la respuesta es realmenteFALSE(porque se detendrá en el momento en que encuentre una falta de coincidencia) y tendrá la misma velocidad como la solución R más rápida si la respuesta esTRUE. Por ejemplo, para el punto de referencia OP, marcasystem.timeexactamente 0 usando esta función.fuente
fast_equal(c(2,1,3), 1.5)a == b,b == cno implica necesariamentea == csi está haciendo comparaciones de punto flotante. Se puede dividir o bien su precisión por el número de elementos para evitar este problema, o modificar el algoritmo para calcularminymaxy usando eso como una condición de parada.Escribí una función específicamente para esto, que puede verificar no solo los elementos en un vector, sino que también es capaz de verificar si todos los elementos de una lista son idénticos . Por supuesto, también maneja bien los vectores de caracteres y todos los demás tipos de vectores. También tiene un manejo de errores apropiado.
Ahora pruebe algunos ejemplos.
fuente
En realidad, no es necesario utilizar min, mean o max. Basado en la respuesta de John:
fuente
Aquí una alternativa que usa el truco mínimo, máximo pero para un marco de datos. En el ejemplo, estoy comparando columnas, pero el parámetro de margen de
applyse puede cambiar a 1 para las filas.Si
valid == 0entonces todos los elementos son igualesfuente