martes, 20 de octubre de 2020

Power Query: Ordenando caracteres por registro

En el día de hoy veremos un par de funciones M (List.Sort y Text.ToList) que nos permitiran descomponer por caracteres y ordenar estos para cada registro de una tabla.
El objetivo sería descomponer cada texto (cada registro) en caracteres individuales, para retornarlos después ordenados alfabéticamente...
Veremos dos métodos:
Power Query: Ordenando caracteres por registro

Como se observa en la imagen, ambos métodos, con igual resultado, ordenan caracteres de cada alfanumérico, i.e., tipo texto!! en esentido ascendente (o descendente si fuera el caso)...
Veamos los pasos a seguir...
Para un primer caso, más 'técnico'.
Desde la Tabla cargamos los datos la editor de Power Query (ficha Datos > grupo Obtener y transformar > Desde tabla o rango); y una vez cargado, y ya en el Editor de PQ, entraremos al editor avanzado y escribimos:
let
    Origen = Excel.CurrentWorkbook(){[Name="Tabla1"]}[Content],
    AddOrdenaCaracteres  = Table.AddColumn(Origen, "Personalizado", each List.Sort(Text.ToList([nombres]))),
    ExtraeValores = Table.TransformColumns(AddOrdenaCaracteres, {"Personalizado", each Text.Combine(_), type text})
in
    ExtraeValores

Power Query: Ordenando caracteres por registro

En este caso la clave del asunto está en la línea donde aplicamos:
List.Sort(Text.ToList([nombres]))

En primer lugar con
Text.ToList(texto as text) : Devuelve una lista de valores de caracteres individuales (uno a uno) a partir del valor de texto especificado... por ejemplo, de 'excelforo' devolvería una lista {e x c e l f o r o}.
Sobre esta lista de caracteres obtenida aplicaremos el orden con
List.Sort(lista as list, optional comparisonCriteria as any): Ordena una lista de datos según los criterios opcionales especificados.
Se puede especificar un parámetro opcional como criterio de comparación, que podría tomar uno de los valores siguientes: Order.Descending, Order.Ascending

Así pues la explicación es simple.. primero descomponemos en caracteres individuales en modo Lista (con Text.ToList) para luego ser ordenados con List.Sort.
Finalmente transformamos la lista obtenida, extrayendo los valores, combinando cada elemento ordenado de esa lista...

Otra manera de trabajarlo más manual, empleando las herramientas disponibles.
En primer lugar cargamos la tabla.
Seguidamente agregamos una columna de Índice (desde 1). Dentro del editor de Power Query, en la ficha Agregar columna > grupo General > Columna Índice > Desde 1
Power Query: Ordenando caracteres por registro

A continuación seleccionaremos el campo 'nombres' (el que deseamos descomponer), y buscaremos en la ficha Inicio > grupo Transformar > Dividir columna > Por número de caracteres
Power Query: Ordenando caracteres por registro

En la ventana diálogo que se abrirá configuraremos las opciones de:
Número de caracteres: 1
Dividir: Varias veces
Avanzadas: Por filas

Esto descompone cada caracter en una fila...
Power Query: Ordenando caracteres por registro

Seguidamente seleccionaremos el campo Índice y presionaremos la opción de Agrupar por (ficha Inicio > grupo Transformar > Agrupar por) lo que abre la siguiente ventana de configuración donde indicaremos que l operación de agrupación es Todas las filas
Power Query: Ordenando caracteres por registro
En la línea de código insertada haremos un cambio:
= Table.Group(#"Dividir columna por posición", {"Índice"}, {{"Ordenados", each _, type table [nombres=nullable text, Índice=number]}})
por
= Table.Group(#"Dividir columna por posición", {"Índice"}, {{"ordenado", each [nombres]}})
Puedes ver aquí otro ejemplo y la explicación.
Un par de pasos más...

En la siguiente etapa expandimos el campo agrupado, presionando las flechitas del encabezado, eligiendo la opción
Extraer valores

Power Query: Ordenando caracteres por registro

En las ventanas siguientes elegiremos como Delimitador para usar en la concatenación de valores de la lista la opción 'Ninguno'
El código generado en este paso:
= Table.TransformColumns(#"Filas agrupadas", {"ordenado", each Text.Combine(List.Transform(_, Text.From)), type text})
lo cambiaremos por
= Table.TransformColumns(#"Filas agrupadas", {"ordenado", each Text.Combine(List.Transform(List.Sort(_), Text.From)), type text})
donde hemos insertado la función List.Sort para que ordene los elementos antes de unirlos de nuevo con Text.Combine.
/
Completando el proceso.

Dos maneras de conseguir nuestro objetivo ;-)

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.