Home » Top 3 Students Per Subject

Top 3 Students Per Subject

Generate Top 3 students in all subjects. The order of subjects in Result table should be same as in source table. In case of duplicates, show the names in the same cell one below the other.

📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 81
Challenge Difficulty: ⭐️⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn

Solving the challenge of Top 3 Students Per Subject with Power Query

Power Query solution 1 for Top 3 Students Per Subject, proposed by Bo Rydobon 🇹🇭:
let
 Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
 Group = Table.FromColumns(List.Accumulate( List.Skip(Table.ColumnNames(Source)),{{1,2,3}}, (s,l)=> s& {List.FirstN(Table.Sort(Table.Group(Source, {l}, 
 {"C", each Text.Combine([#"NameSubject"],"#(lf)")}),{l,1})[C],3)}) , {"Rank"}&List.Skip(Table.ColumnNames(Source)))
in
 Group 


                    
                  
          
Power Query solution 2 for Top 3 Students Per Subject, proposed by Zoran Milokanović:
let
 Source = Excel.CurrentWorkbook(){[Name="Input"]}[Content],
 ToColumns = {{1..3}} & List.Transform(List.Skip(Table.ToColumns(Source)), each List.Accumulate(List.Accumulate({0..2}, {}, (s, c) => s & {List.Max(List.RemoveItems(_, s))}), {}, (s, c) => s & {Text.Combine(List.Transform(List.PositionOf(_, c, 2), each Source[#"NameSubject"]{_}), "#(cr)#(lf)")})),
 Solution = Table.FromColumns(ToColumns, {"Rank"} & List.Skip(Table.ColumnNames(Source)) )
in
 Solution


                    
                  
          
Power Query solution 3 for Top 3 Students Per Subject, proposed by Kris Jaganah:
let
 Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
 #"Replaced Value" = Table.ReplaceValue(Source,null,0,Replacer.ReplaceValue,{"Maths", "English", "Physics", "History", "Social Studies", "Chemistry", "Biology"}),
 #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Replaced Value", {"NameSubject"}, "Attribute", "Value"),
 #"Added Index" = Table.AddIndexColumn(#"Unpivoted Other Columns", "Index", 1, 1, Int64.Type),
 #"Added Custom" = Table.AddColumn(#"Added Index", "Subject Rank", each if Number.Mod([Index],7)= 0 then 7 else Number.Mod([Index],7)),
 #"Grouped Rows" = Table.Group(#"Added Custom", {"Attribute"}, {{"Group", each _, type table [#"NameSubject"=text, Attribute=text, Value=number, Index=number, Subject Rank=number]}}),
 #"Added Custom1" = Table.AddColumn(#"Grouped Rows", "Custom", each Table.AddRankColumn([Group],"Rank",{"Value",Order.Descending},[RankKind=RankKind.Dense])),
 #"Removed Other Columns" = Table.SelectColumns(#"Added Custom1",{"Custom"}),



                    
                  
          
Power Query solution 4 for Top 3 Students Per Subject, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
 Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
 Unpivot = Table.UnpivotOtherColumns(Source, {"NameSubject"}, "Attribute", "Value"),
 Group = Table.Combine(Table.Group(Unpivot, {"Attribute"}, {{"All", each 
 let
 a = Table.FirstN(Table.Sort(Table.Group(_, {"Value", "Attribute"}, {{"All", each Text.Combine([#"NameSubject"], "#(lf)")}}), {"Value", Order.Descending}), 3),
 b = Table.AddIndexColumn(a, "Rank", 1,1)
 in Table.RemoveColumns(b, "Value")}})[All]),
 Sol = Table.SelectColumns(Table.Pivot(Group, List.Distinct(Group[Attribute]), "Attribute", "All"),{"Rank"}&List.Skip(Table.ColumnNames(Source)))
in
 Sol


                    
                  
          
Power Query solution 5 for Top 3 Students Per Subject, proposed by Luan Rodrigues:
let
 Fonte = Tabela1,
 list = List.Skip(Table.ColumnNames(Fonte),1),
 col = Table.UnpivotOtherColumns(Fonte, {"NameSubject"}, "Atributo", "Valor"),
 gp = Table.Group(col, {"Atributo"}, {{"Contagem", each 
 [
 a = List.MaxN(List.Distinct(_[Valor]),3),
 b = Table.AddIndexColumn(Table.Sort(Table.Group(Table.SelectRows(_, each List.Contains(a,[Valor])),{"Valor"},{{"Count", each Text.Combine(_[#"NameSubject"],", ")}}),{"Valor",Order.Descending}) ,"Rank",1,1)
 [[Rank],[Count]]
 ][b]}}),
 class = Table.Sort(gp,each List.PositionOf(list,[Atributo] ) ),
 exp = Table.ExpandTableColumn(class, "Contagem", {"Rank", "Count"}),
 res = Table.Pivot(exp, List.Distinct(exp[Atributo]), "Atributo", "Count")
in
 res


                    
                  
          
Power Query solution 6 for Top 3 Students Per Subject, proposed by Eric Laforce:
let
  Source = Excel.CurrentWorkbook(){[Name = "tData81"]}[Content], 
  Columns = Table.ToColumns(Source), 
  Names = Columns{0}, 
  Subjects = List.Skip(Table.ColumnNames(Source)), 
  Transform = List.Transform(
    List.Skip(Columns), 
    each 
      let
        _Notes = List.Sort(List.Distinct(_), Order.Descending), 
        _Ranks = List.Transform(_, each 1 + List.PositionOf(_Notes, _)), 
        _RN = List.Select(List.Zip({_Ranks, Names}), each _{0} <= 3), 
        _Grp = Table.Group(
          Table.FromRows(_RN, {"R", "N"}), 
          "R", 
          {"GN", each Text.Combine(_[N], "#(lf)")}
        )
      in
        Table.Sort(_Grp, "R")[GN]
  ), 
  ToTable = Table.FromColumns({{1, 2, 3}} & Transform, {"Rank"} & Subjects)
in
  ToTable
Power Query solution 7 for Top 3 Students Per Subject, proposed by Victor Wang:
let
 Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
 Subjects = List.Skip(Table.ColumnNames(Source)),
 Accumulate = List.Accumulate(Subjects, {{1..3}}, (s,c)=> s & {List.Transform({1..3}, (a)=> Lines.ToText(Table.SelectRows( Table.AddRankColumn(Source, "Rank", {c,1} , [RankKind = RankKind.Dense]), (b)=> b[Rank] = a)[#"NameSubject"]))}),
 fromColumns = Table.FromColumns(Accumulate, {"Rank"} & Subjects)
in
 fromColumns


                    
                  
          
Power Query solution 9 for Top 3 Students Per Subject, proposed by Obi E, MPH:
let
 Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
 #"Unpivoted Columns" = Table.UnpivotOtherColumns(Source, {"NameSubject"}, "Attribute", "Value"),
 #"Grouped Rows" = Table.Group(#"Unpivoted Columns", {"Attribute"}, {{"Count", each Table.FirstN(Table.Sort(_,{{"Value", Order.Descending}}),3), type table [#"NameSubject"=text, Attribute=text, Value=number]}}),
 #"Added Custom" = Table.AddColumn(#"Grouped Rows", "Custom", each Table.AddIndexColumn([Count],"Index",1,1)),
 #"Removed Columns1" = Table.RemoveColumns(#"Added Custom",{"Count"}),
 #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns1", "Custom", {"NameSubject", "Attribute", "Value", "Index"}, {"NameSubject", "Attribute.1", "Value", "Index"}),
 #"Removed Columns2" = Table.RemoveColumns(#"Expanded Custom",{"Attribute.1", "Value"}),
 #"Pivoted Column1" = Table.Pivot(#"Removed Columns2", List.Distinct(#"Removed Columns2"[Attribute]), "Attribute", "NameSubject")
in
 #"Pivoted Column1"


                    
                  
          

Solving the challenge of Top 3 Students Per Subject with Excel

Excel solution 1 for Top 3 Students Per Subject, proposed by Bo Rydobon 🇹🇭:
=LET(z,B2:H31,HSTACK({"Rank";1;2;3},VSTACK(B1:H1,MAKEARRAY(3,COLUMNS(z),LAMBDA(r,c,LET(s,INDEX(z,,c),TEXTJOIN("
",,FILTER(A2:A31,s=LARGE(UNIQUE(s),r)))))))))
Excel solution 2 for Top 3 Students Per Subject, proposed by محمد حلمي:
=VSTACK(HSTACK("Rank",B1:H1),HSTACK(ROW(1:3),MAKEARRAY(3,7,LAMBDA(r,c,LET(v,INDEX(B2:H31,,c),INDEX(BYCOL(
IF(v=LARGE(UNIQUE(v),{1,2,3}),A2:A31,""),
LAMBDA(a,TEXTJOIN(CHAR(10),,a))),r))))))
Excel solution 3 for Top 3 Students Per Subject, proposed by Oscar Mendez Roca Farell:
=LET(_e, B1:H1, VSTACK(HSTACK("Rank",_e), REDUCE({1; 2; 3},_e, LAMBDA(i, x, LET(b, INDEX(B2:H31, , XMATCH(x,_e)), HSTACK(i, TEXTSPLIT(TEXTJOIN(";", , BYCOL(REPT(A2:A31, b=LARGE(UNIQUE(b),{1,2,3})), LAMBDA(c, TEXTJOIN(CHAR(10), ,c)))), ,";")))))))
Excel solution 4 for Top 3 Students Per Subject, proposed by Duy Tùng:
=VSTACK(HSTACK("Rank",B1:H1),REDUCE({1;2;3},B2:H2,LAMBDA(x,y,LET(a,TAKE(y:H31,,1),f,LAMBDA(v,TEXTJOIN(CHAR(10),,FILTER(A2:A31,a=LARGE(UNIQUE(a),v)))),HSTACK(x,VSTACK(f(1),f(2),f(3)))))))
Excel solution 5 for Top 3 Students Per Subject, proposed by Sunny Baggu:
=VSTACK(
 HSTACK("Rank", B1:H1),
 HSTACK(
 SEQUENCE(3),
 MAKEARRAY(
 3,
 COLUMNS(B1:H1),
 LAMBDA(r, c,
 TEXTJOIN(
 CHAR(10),
 ,
 FILTER(
 A2:A31,
 INDEX(B2:H31, , c) = LARGE(UNIQUE(INDEX(B2:H31, , c)), r)
 )
 )
 )
 )
 )
)
Excel solution 6 for Top 3 Students Per Subject, proposed by Sunny Baggu:
=HSTACK(
 SEQUENCE(3),
 DROP(
 REDUCE(
 "",
 SEQUENCE(COLUMNS(B1:H1)),
 LAMBDA(x, y,
 HSTACK(
 x,
 DROP(
 REDUCE(
 "",
 LARGE(UNIQUE(INDEX(B2:H31, , y)), SEQUENCE(3)),
 LAMBDA(a, v,
 VSTACK(
 a,
 TEXTJOIN(
 CHAR(10),
 ,
 FILTER(A2:A31, INDEX(B2:H31, , y) = v)
 )
 )
 )
 ),
 1
 )
 )
 )
 ),
 ,
 1
 )
)
Excel solution 7 for Top 3 Students Per Subject, proposed by LEONARD OCHEA 🇷🇴:
=LET(n,A2:A31,d,B2:H31,f,3,c,COLUMNS(d),P,LAMBDA(a,b,LET(c,CHOOSECOLS(d,a),TEXTJOIN(CHAR(10),,FILTER(n,c=LARGE(UNIQUE(c),b))))),HSTACK(VSTACK("Rank",SEQUENCE(f)),VSTACK(B1:H1,MAKEARRAY(f,c,LAMBDA(b,a,P(a,b))))))
Excel solution 8 for Top 3 Students Per Subject, proposed by Pieter de B.:
=LET(data,A1:H31,n,DROP(TAKE(data,,1),1),s,DROP(TAKE(data,1),,1),g,DROP(DROP(data,1),,1),HSTACK({"Rank";1;2;3},VSTACK(s,MAKEARRAY(3,COUNTA(s),LAMBDA(r,c,LET(sg,INDEX(g,,c),TEXTJOIN(CHAR(10),,FILTER(n,sg=LARGE(UNIQUE(sg),r)))))))))
Excel solution 9 for Top 3 Students Per Subject, proposed by Miguel Angel Franco García:
=LET(a;SI.ERROR(INDICE($A:$A;SI(B2:B31=K.ESIMO.MAYOR(UNICOS(B2:B31);1);FILA(B2:B31);SI(B2:B31=K.ESIMO.MAYOR(UNICOS(B2:B31);2);FILA(B2:B31);SI(B2:B31=K.ESIMO.MAYOR(UNICOS(B2:B31);3);FILA(B2:B31);"")));1);"");FILTRAR(a;a<>""))

&&&

Leave a Reply