martes, 4 de octubre de 2022

Power Query: Ordenar por aparición y fila

Me planteaban hace unos días la posibilidad de obtener una numeración ordinal (1,2,3,...) para los distintos valores de cada fila, de acuerdo a su aparción de izquierda a derecha de ciertos campos..
Power Query: Ordenar por aparición y fila


Veremos un par de métodos:
-uno clásico empleando Grupos, columnas de Índice y las opciones de Dinamizar y Anular dinamización
-un segundo empleando Records appoyándonos en la función List.Generate, algo más elegante.

Lo primero será cargar nuestra tabla con ventas ('TblVENTAS') al editor de Power Query, y con la tabla cargada procederemos a generar una segunda consulta como referencia de la tabla subida.
Con la consulta editada, escribimos el siguiente código...
let
    Origen = TblVENTAS,
    //obtenemos los encabezados de la tabla
    Encab=Table.ColumnNames(Origen),
    //ya que a partir de ellos obtendremos automáticamente aquellas columnas que tengan un valor numérico
    //i.e., las columnas con 'años', que serán sobre las que trabajaremos.
    lstFechas=List.Select(Encab, each Value.Is(Value.FromText(_), type number)),
    
    //añadimos un registro compuesto de un dato por cada año
    //autonumerado de izquierda a derecha por orden de aparición
    //siempre que sea distinto de cero
    AddRecord  = Table.AddColumn( Origen, 
                    "DATOS", 
                    each 
                        let
                        Lst=List.ReplaceValue(Record.ToList(Record.SelectFields(_, lstFechas)), null,0, Replacer.ReplaceValue), 
                        num=List.Count(Lst),
                        Acum=List.Generate(
                            () => 
                            [   x = 1, y=if Number.From(Lst{0})<>0 then {1} else {0}],
                            each [x] <=  num,
                            each [  y = if Number.From(Lst{[x]})<>0 then  [y] & {1} else  [y] & {0} ,
                                    x= [x]+1  ],
                            each if List.Last([y])=0 then 0 else List.Sum([y])   )
                        in
                            Record.FromList(Acum, lstFechas) ),
    //discriminamos campos 'viejos' para evitar conflicto con los nuevos generados
    SelCols=Table.SelectColumns(AddRecord,{"País","DATOS"}),
    //expandimos el REgistro
    ExpandeDATOS = Table.ExpandRecordColumn(SelCols, "DATOS", lstFechas, lstFechas)

in
    ExpandeDATOS

Power Query: Ordenar por aparición y fila


El punto interesante de este primer método es que mediante la función List.Generate hemos podido generar un Record, con dos variables x e y, que mediante ciertos condicionales, devuelven el orden buscado 1,2,3,... para aquellos valores distintos de cero!!.
Recuerda los argumentos de la función:
1- punto de inicio
2- punto/condición de salida
3- punto de incremento o siguiente valor
4- punto a devolver

El valor de la x corresponde al contador de valores, mientras que la y responde al valor incremental buscado.
Power Query: Ordenar por aparición y fila


Con el segundo método solo tenemos que usar el asistente de pasos, y seguirlos en la secuencia correcta:
En una secuencia de ocho pasos tendríamos el siguiente código
let
    Origen = TblVENTAS,
    //seleccionamos las columnas de los años y Reemplazamos Valores
    Reemplazo_0_Null = Table.ReplaceValue(Origen,0,null,Replacer.ReplaceValue,{"2021", "2022", "2023", "2024", "2025"}),
    //Seleccionamos la columna País y anulamos la dinamización de las otras columnas
    Anulacion_dinamizacion = Table.UnpivotOtherColumns(Reemplazo_0_Null, {"País"}, "Atributo", "Valor"),
    //Seleccionamos País y agrupamos
    Agrupo_Pais = Table.Group(Anulacion_dinamizacion, {"País"}, {{"Recuento", each _, type table [País=text, Atributo=text, Valor=number]}}),
    //Añadimos una columna personalizada, donde como fórmula incorporamos la que añade una columna índice
    AddIndice = Table.AddColumn(Agrupo_Pais, "ConINDICE", each Table.AddIndexColumn([Recuento],"Id",1,1)),
    //Nos quedamos solo con esta última columna recién creada
    OtrasColumnasQuitadas = Table.SelectColumns(AddIndice,{"ConINDICE"}),
    //y la expandimos
    Expandimos = Table.ExpandTableColumn(OtrasColumnasQuitadas, "ConINDICE", {"País", "Atributo",  "Id"}, {"País", "Atributo",  "Id"}),
    //dinamizamos la columna de Atributo (que corresponde a los Años)
    ColumnaDinamizada = Table.Pivot(Expandimos, List.Distinct(Expandimos[Atributo]), "Atributo", "Id", List.Sum),
    //y finalmente reordenamos o seleccionamos las columnas en el orden deseado
    SelCols=Table.SelectColumns(ColumnaDinamizada, {"País","2021", "2022", "2023", "2024", "2025"})
in
    SelCols


El resultado es el mismo... ;-)

El sentido de este ejercicio podría ser, sobre todo empleando el primer método, recuperar exclusivamente el primer valor de cada registro (o la/s posiciones que neceistáramos).
Un filtro aplicado en el momento-paso adecuado, nos daría el resultado.

No hay comentarios:

Publicar un comentario

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