list - unicos - extraer valores únicos con una fórmula
encontrar valores únicos de una lista (1)
Esta solución sugerida por Marek es la mejor respuesta a la Q original. Vea a continuación para una discusión de otros enfoques y por qué Marek es el más útil.
> unique(unlist(x, use.names = FALSE))
[1] 1 2 3 4 5 6
Discusión
Una solución más rápida es computar unique()
en los componentes de su x
primero y luego hacer un unique()
final unique()
en esos resultados. Esto solo funcionará si los componentes de la lista tienen el mismo número de valores únicos, como lo hacen en los dos ejemplos a continuación. P.ej:
Primero tu versión, luego mi doble enfoque único:
> unique(unlist(x))
[1] 1 2 3 4 5 6
> unique.default(sapply(x, unique))
[1] 1 2 3 4 5 6
Tenemos que llamar a unique.default
ya que hay un método de matrix
para unique
que mantiene un margen fijo; esto está bien ya que una matriz puede ser tratada como un vector.
Marek, en los comentarios a esta respuesta, señala que la velocidad lenta del enfoque de no lista es potencialmente debido a los names
en la lista. La solución de Marek es hacer uso del argumento use.names
para unlist
, que si se usa, resulta en una solución más rápida que la versión única doble anterior. Por la simple x
de la publicación de Roman obtenemos
> unique(unlist(x, use.names = FALSE))
[1] 1 2 3 4 5 6
La solución de Marek funcionará incluso cuando el número de elementos únicos difiera entre los componentes.
Aquí hay un ejemplo más grande con algunos tiempos de los tres métodos:
## Create a large list (1000 components of length 100 each)
DF <- as.list(data.frame(matrix(sample(1:10, 1000*1000, replace = TRUE),
ncol = 1000)))
Aquí están los resultados para los dos enfoques que utilizan DF
:
> ## Do the three approaches give the same result:
> all.equal(unique.default(sapply(DF, unique)), unique(unlist(DF)))
[1] TRUE
> all.equal(unique(unlist(DF, use.names = FALSE)), unique(unlist(DF)))
[1] TRUE
> ## Timing Roman''s original:
> system.time(replicate(10, unique(unlist(DF))))
user system elapsed
12.884 0.077 12.966
> ## Timing double unique version:
> system.time(replicate(10, unique.default(sapply(DF, unique))))
user system elapsed
0.648 0.000 0.653
> ## timing of Marek''s solution:
> system.time(replicate(10, unique(unlist(DF, use.names = FALSE))))
user system elapsed
0.510 0.000 0.512
Lo que muestra que el doble unique
es mucho más rápido al aplicar unique()
a los componentes individuales y luego unique()
esos conjuntos más pequeños de valores únicos, pero esta aceleración se debe únicamente a los names
en la lista DF
. Si le decimos a unlist
que no use los names
, la solución de Marek es ligeramente más rápida que la doble unique
para este problema. Como la solución de Marek está usando la herramienta correcta de manera adecuada, y es más rápida que la alternativa, es la solución preferida.
El gran problema con el doble enfoque unique
es que solo funcionará si , como en los dos ejemplos aquí, cada componente de la lista de entrada ( DF
o x
) tiene el mismo número de valores únicos. En tales casos, sapply
simplifica el resultado a una matriz que nos permite aplicar unique.default
. Si los componentes de la lista de entrada tienen diferentes números de valores únicos, la solución única doble fallará.
Supongamos que tienes una lista de valores
x <- list(a=c(1,2,3), b = c(2,3,4), c=c(4,5,6))
Me gustaría encontrar valores únicos de todos los elementos de la lista combinados. Hasta ahora, el siguiente código hizo el truco
unique(unlist(x))
¿Alguien sabe de una manera más eficiente? Tengo una lista fuerte con muchos valores y apreciaría cualquier aceleración.