martes, febrero 18, 2020

Clasificación (ranking) ordinal con desempate aleatorio

En mi post anterior sobre clasificación (ranking) con Excel y con Power Query mostré un método de desempate basado en un "sorteo", es decir, asignar a cada miembro de la lista un número aleatorio y determinar la posición en caso de empate de acuerdo a ese número.

Como vimos, si usamos la función Number.Random de Power Query todas las filas de la tabla reciben el mismo número.

Buscando en la Internet dí con esta discusión donde se muestran algunas soluciones (aunque la única que funcionó con mi ejemplo fue a basada en List.Random).

Debo confesar que no entiendo cabalmente la solución propuesta que muestro en el post. Esto me produjo un sentimiento de incomodidad que me llevó a buscar mi propia solución.

Recordemos el problema a solucionar:
  • tenemos un a lista de calificaciones de alumno;
  • queremos ordenarla por calificación, de mayor a menor;
  • en caso de "empate" (dos o más alumnos con la misma calificación), realizamos un sorteo para determinar la posición relativa de los "empatados";
  • el sorteo lo hacemos calculando un número aleatorio para cada alumno. Luego ordenamos los empates de acuerdo al número aleatorio que recibió cada alumno.

La solución que desarrollé esta basada en la función Number.Random y en un "truco": combinar la consulta consigo misma.

Estos son los pasos aplicados partiendo de esta tabla de datos:



1 - creamos la conexión a la tabla de calificaciones.

2 - agrupamos la tabla por [Alumno] utilizando la operación Todas las filas 


3 - Agregamos una columna personalizada con la fórmula =Number.Random()


Podemos que en este estado de la tablas Number.Random da un número aleatorio distinto a cada fila.

4 - Combinamos la tabla consigo misma (si, está permitido) usando el campo [Alumno] 

5 - Expandimos la columna[filas.1] extrayendo solo la columna [filas] (la columna que creamos en el paso 2 y que contiene todas las filas de la tabla original


6 - Quitamos todas la columnas excepto [Custom] y [filas.1]


7 - Expandimos [filas.1] y extraemos todas las columnas


8 - Ordenamos la tabla por [Calificacion] y por [Custom]

Nótese los números 1 y 2 al lado de las flechas indicando la secuencia del orden (primero por [Calificacion] y luego pot [Custom]

9 - Eliminamos la columna [Custom] y agregamos una columna Índice para indicar el número de posición y descargamos la consulta a la hoja de Excel.

El código de la la consulta


 let  
   Source = tbl_Alumnos,  
   AgruparFilas = Table.Group(Source, {"Alumno"}, {{"filas", each _, type table}}),  
   Agregar_Aleatorio = Table.AddColumn(AgruparFilas, "Custom", each Number.Random()),  
   Combinar = Table.NestedJoin(Agregar_Aleatorio,{"Alumno"},Agregar_Aleatorio,{"Alumno"},"Added Custom",JoinKind.LeftOuter),  
   Expandir_solo_filas = Table.ExpandTableColumn(Combinar, "Added Custom", {"filas"}, {"filas.1"}),  
   Quitar_columnas = Table.RemoveColumns(Expandir_solo_filas,{"filas", "Alumno"}),  
   Expandir_filas.1 = Table.ExpandTableColumn(Quitar_columnas, "filas.1", {"Alumno", "Calificacion"}, {"Alumno", "Calificacion"}),  
   Ordenar = Table.Sort(Expandir_filas.1,{{"Calificacion", Order.Descending}, {"Custom", Order.Ascending}}),  
   Quitar_aleatorio = Table.RemoveColumns(Ordenar,{"Custom"}),  
   Agregar_indice = Table.AddIndexColumn(Quitar_aleatorio, "Index", 1, 1)  
 in  
   Agregar_indice  


No hay comentarios.:

Publicar un comentario

Nota: sólo los miembros de este blog pueden publicar comentarios.