Home » Group Data Within Sale Limit

Group Data Within Sale Limit

Divide the data into groups sequentially such that sum of Sale in a group should not exceed 20 and should be as close to 20 as possible in a group. Example – For first 4 rows, 7+5+7=19 and next entry is 8. Hence, Group1 will be 7+5+7 only as 7+5+7+8 will exceed 20, hence group 2 will start from 8. Note – The maximum value Sale column can contain is 20.

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

Solving the challenge of Group Data Within Sale Limit with Power Query

Power Query solution 1 for Group Data Within Sale Limit, proposed by Bo Rydobon 🇹🇭:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Group = List.Transform(
    List.Accumulate(
      List.Zip(
        {
          List.Accumulate(
            Source[Sale], 
            {}, 
            (s, v) =>
              let
                a = List.Last(s, 0), 
                b = Number.From(a + v < 21) * a + v
              in
                s & {b}
          ), 
          Source[Sale]
        }
      ), 
      {}, 
      (g, l) => g & {List.Last(g, 0) + Number.From(l{0} = l{1})}
    ), 
    each "Group" & Text.From(_)
  ), 
  Ans = Table.FromColumns(Table.ToColumns(Source) & {Group}, Table.ColumnNames(Source) & {"Group"})
in
  Ans
Power Query solution 2 for Group Data Within Sale Limit, proposed by Zoran Milokanović:
let
  Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content], 
  G = "Group", 
  I = each G & Text.From(Number.From(Text.End(_, Text.Length(_) - 5)) + 1), 
  S = Table.FromRows(
    List.Accumulate(
      Table.ToRows(Source), 
      {}, 
      (s, c) =>
        s
          & {
            let
              l = List.Last(s, {"", 0, G & "1"}), 
              g = l{2}, 
              m = List.Sum(List.Zip(List.Select(s, each _{2} = g)){1}? ?? {0})
            in
              c & {if m + c{1} <= 20 then g else I(g)}
          }
    ), 
    Table.ColumnNames(Source) & {G}
  )
in
  S
Power Query solution 3 for Group Data Within Sale Limit, proposed by Kris Jaganah:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Index = Table.AddIndexColumn(Source, "Index", 1, 1, Int64.Type), 
  Cumul20 = Table.AddColumn(
    Index, 
    "First20", 
    each List.Accumulate(
      List.Range(Index[Sale], 0, [Index]), 
      0, 
      (P, C) => if P + C > 20 then C else P + C
    )
  ), 
  Group = Table.AddColumn(
    Cumul20, 
    "Group", 
    each 
      let
        a = Table.AddColumn(Cumul20, "Custom", each if [Sale] = [First20] then 1 else 0)[Custom], 
        b = List.Accumulate(List.Range(a, 0, [Index]), 0, (X, Y) => X + Y), 
        c = "Group" & Text.From(b)
      in
        c
  ), 
  Remove = Table.RemoveColumns(Group, {"Index", "First20"})
in
  Remove
Power Query solution 4 for Group Data Within Sale Limit, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Grupos = List.Transform(
    List.Skip(
      List.Generate(
        () => [x = 0, y = 0, z = 1], 
        each [x] <= Table.RowCount(Source), 
        each [
          y = if [y] + Source[Sale]{[x]} > 20 then Source[Sale]{[x]} else [y] + Source[Sale]{[x]}, 
          z = if [y] + Source[Sale]{[x]} > 20 then [z] + 1 else [z], 
          x = [x] + 1
        ], 
        each [z]
      )
    ), 
    each "Group" & Text.From(_)
  ), 
  Sol = Table.FromColumns(Table.ToColumns(Source) & {Grupos}, Table.ColumnNames(Source) & {"Group"})
in
  Sol
Power Query solution 5 for Group Data Within Sale Limit, proposed by Alexis Olson:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Table1 = Table.TransformColumnTypes(Source, {{"Name", type text}, {"Sale", Int64.Type}}), 
  Sales = Table1[Sale], 
  GroupCol = List.Generate(
    () => [i = 0, sum = Sales{0}, group = 1], 
    each [i] < List.Count(Sales), 
    each [
      i     = [i] + 1, 
      sum   = if [sum] + Sales{i} > 20 then Sales{i} else [sum] + Sales{i}, 
      group = if [sum] + Sales{i} > 20 then [group] + 1 else [group]
    ], 
    each "Group" & Number.ToText([group])
  ), 
  AddCol = Table.FromColumns(Table.ToColumns(Table1) & {GroupCol}, {"Name", "Sale", "Group"})
in
  AddCol
Power Query solution 6 for Group Data Within Sale Limit, proposed by Eric Laforce:
let
  Source = Excel.CurrentWorkbook(){[Name = "tData119"]}[Content], 
  AddGroup = List.Accumulate(
    Table.ToRows(Source), 
    [t = 0, g = 1, r = {}], 
    (s, c) =>
      let
        _t = s[t] + c{1}
      in
        if (_t <= 20) then
          [t = _t, g = s[g], r = s[r] & {c & {s[g]}}]
        else
          [t = c{1}, g = s[g] + 1, r = s[r] & {c & {s[g] + 1}}]
  )[r], 
  ToTable = Table.FromRows(AddGroup, Table.ColumnNames(Source) & {"Group"}), 
  TransformGroup = Table.TransformColumns(ToTable, {"Group", each "Group" & Text.From(_)})
in
  TransformGroup
Power Query solution 7 for Group Data Within Sale Limit, proposed by Sandeep Marwal:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Custom1 = List.Skip(
    List.Accumulate(
      Source[Sale], 
      {0}, 
      (c, v) => if List.Last(c) + v <= 20 then c & {v + List.Last(c)} else c & {v}
    )
  ), 
  Custom2 = Table.FromColumns(Table.ToColumns(Source) & {Custom1}), 
  #"Added Conditional Column" = Table.AddColumn(
    Custom2, 
    "Custom", 
    each if [Column2] = [Column3] then "G" else null
  ), 
  #"Grouped Rows" = Table.Group(
    #"Added Conditional Column", 
    {"Custom"}, 
    {
      {
        "Count", 
        each _, 
        type table [Column1 = text, Column2 = number, Column3 = number, Custom = nullable text]
      }
    }, 
    0, 
    (c, n) => Number.From(n[Custom] = "G")
  ), 
  #"Added Index" = Table.AddIndexColumn(#"Grouped Rows", "Index", 1, 1, Int64.Type), 
  #"Expanded Count" = Table.ExpandTableColumn(
    #"Added Index", 
    "Count", 
    {"Column1", "Column2", "Column3", "Custom"}, 
    {"Column1", "Column2", "Column3", "Custom.1"}
  ), 
  #"Removed Other Columns" = Table.SelectColumns(#"Expanded Count", {"Column1", "Column2", "Index"}), 
  #"Renamed Columns" = Table.RenameColumns(
    #"Removed Other Columns", 
    {{"Column1", "Name"}, {"Column2", "Sale"}, {"Index", "Group"}}
  ), 
  #"Added Prefix" = Table.TransformColumns(
    #"Renamed Columns", 
    {{"Group", each "Group" & Text.From(_, "en-IN"), type text}}
  )
in
  #"Added Prefix"

Solving the challenge of Group Data Within Sale Limit with Excel

Excel solution 1 for Group Data Within Sale Limit, proposed by Bo Rydobon 🇹🇭:
=HSTACK(A1:B26,VSTACK("Group","Group"&SCAN(0,SCAN(,B2:B26,LAMBDA(a,v,(a+v<21)*a+v))=B2:B26,LAMBDA(a,v,a+v))))
Excel solution 2 for Group Data Within Sale Limit, proposed by محمد حلمي:
=LET(
e,REDUCE(0,A2:A20,LAMBDA(a,v,LET(
d,TAKE(v:B20,1),VSTACK(a,IF(d,TAKE(a,-1)+d,d))))),
x,FILTER(e,TAKE(e,,1)*(VSTACK(DROP(e,1,-1)=0,1))),
i,"Group",VSTACK(HSTACK(i,A1:B1),
HSTACK(i&SEQUENCE(ROWS(x)),x)))
Excel solution 3 for Group Data Within Sale Limit, proposed by محمد حلمي:
=HSTACK(A1:B26,"Group"&VSTACK("",SCAN(0,B2:B26=SCAN(0,B2:B26,LAMBDA(a,d,IF(a+d<21,a+d,d))),LAMBDA(a,d,a+d))))
Excel solution 4 for Group Data Within Sale Limit, proposed by محمد حلمي:
="Group"&
REDUCE("",
B2:B26=REDUCE(,B2:B26,LAMBDA(a,d,VSTACK(a,
IF(TAKE(a,-1)+d<21,TAKE(a,-1)+d,d)))),
LAMBDA(a,d,VSTACK(a,TAKE(N(a),-1)+d)))
Excel solution 5 for Group Data Within Sale Limit, proposed by محمد حلمي:
="Group"&
SCAN(0,
B2:B26=SCAN(0,B2:B26,LAMBDA(a,d,IF(a+d<21,a+d,d))),
LAMBDA(a,d,a+d))
Excel solution 6 for Group Data Within Sale Limit, proposed by محمد حلمي:
="Group"&
SCAN(0,B2:B26=
SCAN(0,E2:E26,LAMBDA(a,d,IF(a+d<21,a+d,d))),
LAMBDA(a,d,a+d))
Excel solution 7 for Group Data Within Sale Limit, proposed by محمد حلمي:
="Group"&SCAN(0,B2:B26=SCAN(0,E2:E26,LAMBDA(a,d,IF(a+d<21,a+d,d))),LAMBDA(a,d,a+d))
Excel solution 8 for Group Data Within Sale Limit, proposed by Kris Jaganah:
=LET(a,A2:A26,b,B2:B26,VSTACK({"Name","Sale","Group"},HSTACK(a,b,"Group"&SCAN(0,SCAN(0,b,LAMBDA(x,y,IF(y+x>20,y,y+x)))=b,LAMBDA(v,w,IF(w,1+v,v))))))
Excel solution 9 for Group Data Within Sale Limit, proposed by Oscar Mendez Roca Farell:
=LET(_m,MAP(B2:B26, LAMBDA(b, SUM(B2:b))), HSTACK(A1:B26, VSTACK("Group","Group"&1+INT(MROUND(_m, 10)/20))))
Excel solution 10 for Group Data Within Sale Limit, proposed by Sunny Baggu:
=LET(
 _sale, B2:B26,
 _sumsale, SCAN(
 0,
 _sale,
 LAMBDA(a, v, IF(a + v <= 21, a + v, v))
 ),
 HSTACK(
 A2:B26,
 "Group" & SCAN(0, _sale = _sumsale, LAMBDA(a, v, a + v))
 )
)
Excel solution 11 for Group Data Within Sale Limit, proposed by Anup Kumar:
=HSTACK(A2:B26,"Group"&LET(
sale,B2:B26,
sm, SCAN(0,sale,LAMBDA(x,y,IF(x+y>20,y,x+y))),
SCAN(0,sm-sale,LAMBDA(a,b,IF(b,a,a+1))))
)

Solving the challenge of Group Data Within Sale Limit with Python in Excel

Python in Excel solution 1 for Group Data Within Sale Limit, proposed by Bo Rydobon 🇹🇭:
df =xl("A1:B26", headers = True)
c,g =0,0
df['Group']=['Group'+str(g:=g+(c==s)) for s in df.Sale if (c:=(c+s<21)*c+s)]
df
Python in Excel solution 2 for Group Data Within Sale Limit, proposed by 🇰🇷 Taeyong Shin:
df = xl("A1:B26", headers=True)
def group_num(sales):
 new_list = list()
 cumsum = 0
 gn = 1
 for n in sales:
 cumsum += n
 if cumsum > 20:
 gn += 1
 cumsum = n
 new_list.append(f'Group{gn}')
 return new_list
df.assign(Group = group_num(df['Sale']))
                    
                  

&&&

Leave a Reply