Más sobre factores, strings y ordenación
Esta entrada debería ser un comentario más en esta otra, pero voy a abusar del privilegio de ser dueño de la plataforma para promocionarla.
Voy a decir cosas que son aproximadamente ciertas. Los detalles de la verdad de todo están en la ayuda y el código de sort
y sus métodos.
En R hay dos métodos de ordenación: shell
y radix
. El primero es genérico y el segundo es mejor cuando en el vector hay muchos elementos repetidos (p.e., ordenar el censo por provincias).
R utiliza ciertas reglas para determinar cuándo usar uno u otro. Por ejemplo, para factores usa radix
. También para ordenar vectores largos de enteros pequeños. Etc. Si no, usa shell
. En particular, usa shell
por defecto para ordenar strings.
Por tanto, si codificas las provincia como string
en un conjunto de datos tan grande como el censo y tratas de ordenar, te estás disparando en el pie. Así debe entenderse el consejo de Iñaki Úcar (en el hilo antes mencionado) de que
[s]iempre es mejor tener factores que cadenas.
A nadie le gustan los factores. Mucha gente los desaconseja y clama por cambiar el criterio de R de leer columnas de texto como factores por defecto. Úcar, que tiene el vicio de equivocarse poco, recomienda lo contrario en este contexto concreto, entiendo.
Tampoco se equivoca cuando dice que
[e]l hecho de que R almacene las cadenas de forma única y tenga punteros a ellas es un tema de eficiencia de memoria, pero supone poca o nula diferencia a la hora de ordenar.
Es cierto (aquí y hoy) pero podría no serlo en el futuro. Alguien podría reimplementar sort
para strings diciendo: siempre que el vector de valores únicos del vector sea mucho más corto que el del vector, úsese radix
. En principio, no veo por qué no podría hacerse.
Finalmente, sí, es evidente que es mucho más sencillo comparar enteros que comparar cadenas de texto. Sobre todo en el mundo extra-ASCII. Pero iguales algoritmos de ordenación deberían realizar el mismo número de comparaciones (en el ejemplo que propuse en la entrada arriba mencionada) y el coste adicional de la ordenación debería ser lineal con la complejidad de la función de comparación… y eso es solo la mitad de la historia que parece que explica el misterio.
En resumen, la diferencia fundamental entre el tiempo de ordenación de enteros, factores y strings tiene dos causas fundamentales:
- La complejidad de la función de comparación entre parejas de elementos (enteros o strings) para determinar cuál es mayor.
- Las reglas que hacen que se use
radix
oshell
como algoritmo de ordenación.
Y aventuraría, además, que la segunda pesa más que la primera. Cosa que es fácil de probar y refutar y que dejo como ejercicio a alguno de mis lectores que, a diferencia de servidor, esté de vacaciones.