Home » Add Index Column! Part 4

Add Index Column! Part 4

Solving Add Index Column Part 4 challenge by Power Query, Power BI, Excel, Python and R

Add an index column to the question table, with a separate counter for each stock. Restart the index from 1 each time the price drops

📌 Challenge Details and Links
Challenge Number: 127
Challenge Difficulty: ⭐⭐
📥Download Sample File
📥Link to the solutions on LinkedIn
📥Link to the solution on YouTube

Solving the challenge of Add Index Column! Part 4 with Power Query

Power Query solution 1 for Add Index Column! Part 4, proposed by Zoran Milokanović:
let
  Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content], 
  S = Table.FromRows(
    List.Accumulate(
      Table.ToRows(Source), 
      {}, 
      (b, n) =>
        let
          l = List.Last(List.Select(b, each _{0} = n{0}), {0, 0, 0})
        in
          b & {n & {{l{2} + 1, 1}{Byte.From(n{1} < l{1})}}}
    ), 
    Table.ColumnNames(Source) & {"index"}
  )
in
  S
Power Query solution 2 for Add Index Column! Part 4, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Idx = Table.AddIndexColumn(Source, "Idx"),
Group = Table.Group(Idx, {"Stock"}, {{"A", each 
 let
 a = _,
 b = List.Generate(()=> [k=0, z=1],
 each [k] < List.Count(a[Idx]),
 each [y = a[Price]{k}>a[Price]{[k]},
 z = if y then [z]+1 else 1,
 k = [k]+1],
 each [z]),
 c = Table.FromColumns({a[Price], b, a[Idx]}, {"Price", "Index", "B"})
 in c}},1),
Sol = Table.RemoveColumns(Table.Sort(Table.ExpandTableColumn(Group, "A", 
 Table.ColumnNames(Group[A]{0})), "B"),"B")
in
Sol
Power Query solution 3 for Add Index Column! Part 4, proposed by Abdallah Ally:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Combine = Table.Combine(
    List.Transform(
      List.Distinct(Source[Stock]), 
      each [
        a = Table.SelectRows(Source, (x) => x[Stock] = _), 
        b = List.Accumulate(
          {1 .. Table.RowCount(a) - 1}, 
          {1}, 
          (x, y) => if a[Price]{y} < a[Price]{y - 1} then x & {1} else x & {List.Last(x) + 1}
        ), 
        c = Table.FromColumns(Table.ToColumns(a) & {b}, {"Stock", "Price", "index"})
      ][c]
    )
  ), 
  Result = Table.Sort(Combine, each Table.PositionOf(Source, _[[Stock], [Price]]))
in
  Result
Power Query solution 4 for Add Index Column! Part 4, proposed by Kris Jaganah:
let
  A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  B = Table.AddIndexColumn(A, "Id"), 
  C = Table.Group(
    B, 
    {"Stock"}, 
    {
      "All", 
      each 
        let
          a = Table.AddIndexColumn(_, "In"), 
          b = Table.AddColumn(a, "Di", each [Price] - (try a[Price]{[In] - 1} otherwise [Price])), 
          c = Table.AddColumn(
            b, 
            "Index", 
            each List.Accumulate(
              List.FirstN(b[Di], [In] + 1), 
              0, 
              (x, y) => if y >= 0 then x + 1 else 1
            )
          )
        in
          c
    }
  )[All], 
  D = Table.Combine(C), 
  E = Table.Sort(D, {"Id", 0})[[Stock], [Price], [Index]]
in
  E
Power Query solution 5 for Add Index Column! Part 4, proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
S= Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
A = Table.AddIndexColumn(S, "I", 1, 1),
B = Table.Group(A, {"Stock"}, {{"T", each _}}),
C = Table.AddColumn(B, "F", each F([T])),
F=(x)=>
let
a = Table.AddIndexColumn(x, "In", 0, 1),
b = Table.AddColumn(a, "C", each try if [Price]-a[Price]{[In]-1}<0 then [In] else null otherwise [In]),
c = Table.FillDown(b,{"C"}),
d = Table.Group(c, {"C"}, {{"T", each _}}),
e = Table.AddColumn(d, "T2", each Table.AddIndexColumn([T],"Index",1,1)),
f = Table.SelectColumns(e,{"T2"}),
g = Table.ExpandTableColumn(f, "T2", {"Stock", "Price", "I", "In", "C", "Index"}, {"Stock", "Price", "I", "In", "C", "Index"}),
h = Table.SelectColumns(g,{"Stock", "Price", "I", "Index"})
in
h,
D = Table.SelectColumns(C,{"F"}),
E = Table.ExpandTableColumn(D, "F", {"Stock", "Price", "I", "Index"}, {"Stock", "Price", "I", "Index"}),
G =Table.Sort(E,{{"I", Order.Ascending}}),
H = Table.RemoveColumns(G,{"I"})
in
H
Power Query solution 6 for Add Index Column! Part 4, proposed by Sahan Jayasuriya:
let
  Source = Excel.CurrentWorkbook(){[Name = "Data"]}[Content], 
  AddedSortIndex = Table.AddIndexColumn(Source, "MainIndex", 1, 1, Int64.Type), 
  GroupedRows = Table.Group(AddedSortIndex, {"Stock"}, {{"All", each _}}), 
  AddedSubIndex = Table.TransformColumns(
    GroupedRows, 
    {{"All", each Table.AddIndexColumn(_, "SubIndex", 0, 1)}}
  ), 
  AddedRequiredIndex = Table.TransformColumns(
    AddedSubIndex, 
    {
      {
        "All", 
        each Table.AddColumn(
          _, 
          "Index", 
          (k) =>
            [
              a = List.RemoveLastN(List.Positions(_[Price]), 1), 
              b = List.Accumulate(
                a, 
                {1}, 
                (s, c) => if _[Price]{c + 1} >= _[Price]{c} then s & {List.Last(s) + 1} else s & {1}
              )
            ][b]{k[SubIndex]}
        )
      }
    }
  ), 
  ExpandedTable = Table.ExpandTableColumn(
    AddedRequiredIndex, 
    "All", 
    {"Price", "MainIndex", "Index"}
  ), 
  SortedRows = Table.Sort(ExpandedTable, {{"MainIndex", Order.Ascending}}), 
  RequiredCols = Table.SelectColumns(SortedRows, {"Stock", "Price", "Index"})
in
  RequiredCols

Solving the challenge of Add Index Column! Part 4 with Excel

Excel solution 1 for Add Index Column! Part 4, proposed by Bo Rydobon 🇹🇭:
=REDUCE(E2:G2,
    C3:C13,
    LAMBDA(a,
    p,
    LET(v,
    TAKE(
        B13:p,
        1
    ),
    s,
    @+v,
    f,
    TAKE(
        FILTER(
            a,
            TAKE(
                a,
                ,
                1
            )=s,
            {0,
            0,
            0}
        ),
        -1
    ),
    VSTACK(a,
    HSTACK(v,
    (p>INDEX(
        f,
        2
    ))*INDEX(
        f,
        3
    )+1)))))
Excel solution 2 for Add Index Column! Part 4, proposed by Bo Rydobon 🇹🇭:
=LET(
    s,
    B3:B13,
    DROP(
        REDUCE(
            0,
            UNIQUE(
                s
            ),
            LAMBDA(
                a,
                x,
                LET(
                    p,
                    FILTER(
                        C3:C13,
                        s=x
                    ),
                    SORT(
                        VSTACK(
                            a,
                            HSTACK(
                                FILTER(
                                    ROW(
                s
            ),
                                    s=x
                                ),
                                SCAN(
                                    0,
                                    DROP(
                                        VSTACK(
                                            0,
                                            p
                                        ),
                                        -1
                                    )
Excel solution 3 for Add Index Column! Part 4, proposed by 🇰🇷 Taeyong Shin:
=LET(     z,
     B3:C13,     d,
     BYROW(
         z,
          CONCAT
     ) & ROW(
         DROP(
             z,
             ,
              1
         )
     )%,     s,
     SORT(
         HSTACK(
             XMATCH(
                 d,
                  d
             ),
              z
         ),
          2
     ),     Th,
     SCAN(
         LAMBDA(
             {0,
             0}
         ),
          DROP(
              s,
              ,
               2
          ),
          LAMBDA(
              a,
              v,
              
               LAMBDA(
                   IF(
                       v > INDEX(
                           a(),
                            2
                       ),
                        HSTACK(
                            @a() + 1,
                             v
                        ),
                        HSTACK(
                            1,
                             v
                        )
                   )
               )
               
          )
     ),     SORTBY(
         HSTACK(
             DROP(
                 s,
                 ,
                  1
             ),
              MAP(
                  Th,
                   LAMBDA(
                       f,
                        @f() 
                   )
              )
         ),
          TAKE(
                 s,
                 ,
                  1
             )
     ))
Excel solution 4 for Add Index Column! Part 4, proposed by 🇰🇷 Taeyong Shin:
=LET(z,
    B3:C13,
    d,
    BYROW(
        z,
        CONCAT
    )&ROW(
        DROP(
            z,
            ,
            1
        )
    )%,
    s,
    SORT(
        HSTACK(
            XMATCH(
                d,
                d
            ),
            z
        ),
        2
    ),
    p,
    DROP(
        s,
        ,
        2
    ),
    a,
    INDEX(
        s,
        ,
        2
    ),
    b,
    (p>DROP(
        VSTACK(
            0,
            p
        ),
        -1
    ))*(a=DROP(
        VSTACK(
            @a,
            a
        ),
        -1
    )),
    SORTBY(
        HSTACK(
            DROP(
                s,
                ,
                1
            ),
            SCAN(
                0,
                b,
                LAMBDA(
                    a,
                    v,
                    IF(
                        v,
                        a+1,
                        1
                    )
                )
            )
        ),
        TAKE(
                s,
                ,
                1
            )
    ))
Excel solution 5 for Add Index Column! Part 4, proposed by Aditya Kumar Darak 🇮🇳:
=LET(     _stock,
     B3:B13,     _price,
     C3:C13,     _seq,
     SEQUENCE(
         ROWS(
             _stock
         )
     ),     _sort1,
     SORT(
         HSTACK(
             _seq,
              _stock,
              _price
         ),
          2
     ),     _scan,
     SCAN(          0,          _seq,          LAMBDA(
              a,
               b,
              
               IFS(
                   
                    AND(
                        INDEX(
                            _sort1,
                             b - 1,
                             2
                        ) <> INDEX(
                            _sort1,
                             b,
                             2
                        )
                    ),
                   
                    1,
                   
                    AND(
                        INDEX(
                            _sort1,
                             b - 1,
                             3
                        ) > INDEX(
                            _sort1,
                             b,
                             3
                        )
                    ),
                   
                    1,
                   
                    1,
                   
                    a + 1
                    
               )
               
          )     ),     _sort2,
     SORT(
         HSTACK(
             _sort1,
              _scan
         )
     ),     _rtrn,
     DROP(
         _sort2,
          ,
          1
     ),     _rtrn)
Excel solution 6 for Add Index Column! Part 4, proposed by Aditya Kumar Darak 🇮🇳:
=LET(     _seq,
     SEQUENCE(
         ROWS(
             B3:C13
         )
     ),     _stack1,
     HSTACK(
         _seq,
          B3:C13
     ),     _sort1,
     SORT(
         _stack1,
          2
     ),     _thunk,
     BYROW(
         _sort1,
          LAMBDA(
              a,
               LAMBDA(
                   a
               )
          )
     ),     _scan,
     SCAN(          0,          _seq,          LAMBDA(
              a,
               b,
              
               LET(
                   
                    prev,
                    INDEX(
                        INDEX(
                            _thunk,
                             b - 1
                        ),
                         1,
                         1
                    )(),
                   
                    curr,
                    INDEX(
                        INDEX(
                            _thunk,
                             b
                        ),
                         1,
                         1
                    )(),
                   
                    rtrn,
                    IF(
                        OR(
                            INDEX(
                                prev,
                                 2
                            ) <> INDEX(
                                curr,
                                 2
                            ),
                             INDEX(
                                 curr,
                                  3
                             ) < INDEX(
                                 prev,
                                  3
                             )
                        ),
                         1,
                         a + 1
                    ),
                   
                    rtrn
                    
               )
               
          )     ),     _stack2,
     HSTACK(
         _sort1,
          _scan
     ),     _sort2,
     SORT(
         _stack2
     ),     _rtrn,
     DROP(
         _sort2,
          ,
          1
     ),     _rtrn)
Excel solution 7 for Add Index Column! Part 4, proposed by Oscar Mendez Roca Farell:
=LET(
    s,
     B3:B13,
     p,
     C3:C13,
     VSTACK(
         E2:G2,
          HSTACK(
              s,
               p,
               MAP(
                   s,
                    p,
                    LAMBDA(
                        b,
                         c,
                         LET(
                             f,
                              FILTER(
                                  C3:c,
                                  B3:b=b
                              ),
                              n,
                              N(
                                  VSTACK(
                                      0,
                                      DROP(
                                          f,
                                          -1
                                      )
                                  )>f
                              ),
                              IFNA(
                                  ROWS(
                                      n
                                  )-XMATCH(
                                      1,
                                      n,
                                      ,
                                      -1
                                  )+1,
                                  1
                              )
                         )
                    )
               )
          )
     )
)
Excel solution 8 for Add Index Column! Part 4, proposed by Julian Poeltl:
=LET(
    S,
    B3:B13,
    P,
    C3:C13,
    MAP(
        SEQUENCE(
            ROWS(
                S
            )
        ),
        LAMBDA(
            A,
            LET(
                F,
                FILTER(
                    TAKE(
                        P,
                        A
                    ),
                    TAKE(
                        S,
                        A
                    )=INDEX(
                        S,
                        A
                    )
                ),
                TAKE(
                    SCAN(
                        0,
                        --IFERROR(
                            DROP(
                                F
Excel solution 9 for Add Index Column! Part 4, proposed by Kris Jaganah:
=CHOOSECOLS(
    SORT(
        REDUCE(
            {"Stock",
            "Price",
            "",
            "index"},
            UNIQUE(
                B3:B13
            ),
            LAMBDA(
                x,
                y,
                VSTACK(
                    x,
                    LET(
                        a,
                        B3:B13,
                        c,
                        -SEQUENCE(
                            ROWS(
                                a
                            )
                        ),
                        d,
                        FILTER(
                            HSTACK(
                                a,
                                C3:C13,
                                c
                            ),
                            a=y
                        ),
                        e,
                        INDEX(
                            d,
                            ,
                            2
                        ),
                        f,
                        SCAN(
                            1,
                            e-VSTACK(
                                @e,
                                DROP(
                                    e,
                                    -1
                                )
                            ),
                            LAMBDA(
                                x,
                                y,
                                IF(
                                    y>0,
                                    1+x,
                                    1
                                )
                            )
                        ),
                        HSTACK(
                            d,
                            f
                        )
                    )
                )
            )
        ),
        3,
        -1
    ),
    1,
    2,
    4
)
Excel solution 10 for Add Index Column! Part 4, proposed by Imam Hambali:
=LET(
l,
     LAMBDA(
         x,
         y,
         z,
          DROP(
              CHOOSECOLS(
                  x,
                  y
              ),
              z
          )
     ),a,
     SORT(
         HSTACK(
             B3:C13,
              SEQUENCE(
                  ROWS(
                      B3:C13
                  )
              )
         ),
         1,
         1
     ),d,
     (l(
         a,
         1,
         0
     )=VSTACK(
         0,
         l(
             a,
             1,
             -1
         )
     ))*1,e,
     0+(l(
         a,
         2,
         0
     )>VSTACK(
         0,
          l(
              a,
              2,
              -1
          )
     )),y,
     SCAN(0,
     (d>0)*(e=1),
     LAMBDA(
         x,
         y,
          IF(
              y=0,
              1,
              x+y
          )
     )),CHOOSECOLS(
    SORT(
        HSTACK(
            a,
            y
        ),
        3,
        1
    ),
    1,
    2,
    4
)
)
Excel solution 11 for Add Index Column! Part 4, proposed by Ankur Sharma:
=IF(
    COUNTIFS(
        $E$3:E3,
         E4
    ) = 0,
     1,
     IF(
         F4 < XLOOKUP(
             E4,
              $E$3:E3,
              $F$3:F3,
              ,
              ,
              -1
         ),
          1,
          XLOOKUP(
              E4,
               $E$3:E3,
               $G$3:G3,
               ,
               ,
               -1
          ) + 1
     )
)
Excel solution 12 for Add Index Column! Part 4, proposed by Bruno Mérola, CFA, FRM, CIPM:
=LET(
 rkg, SORT(HSTACK(ROW(B3:C13), B3:C13), 2),
 idx, SCAN(, SEQUENCE(ROWS(rkg)), LAMBDA(a,i,
 IF(AND(i > 1, INDEX(rkg, i, 2) = INDEX(rkg, i - 1, 2), INDEX(rkg, i, 3) >= INDEX(rkg, i -1, 3)), a) + 1)),
 SORTBY(idx, INDEX(rkg, , 1)))
Excel solution 13 for Add Index Column! Part 4, proposed by Rick Rothstein:
=LET(
    i,
    INDEX,
    q,
    SEQUENCE,
    k,
    VSTACK,
    c,
    COUNT(
        C3:C13
    ),
    s,
    SORT(
        HSTACK(
            q(
                c
            ),
            B3:C13
        ),
        2,
        1
    ),
    t,
    k(
        0,
        TAKE(
            s,
            ,
            -1
        )
    ),
    tt,
    k(
        0,
        CHOOSECOLS(
            s,
            2
        )
    ),
    k(
        "Index",
        SORTBY(
            SCAN(
                ,
                q(
                c
            ),
                LAMBDA(
                    a,
                    x,
                    IF(
                        i(
                            tt,
                            x
                        )<>i(
                            tt,
                            x+1
                        ),
                        1,
                        IF(
                            i(
                                t,
                                x
                            )

Solving the challenge of Add Index Column! Part 4 with Python

Python solution 1 for Add Index Column! Part 4, proposed by Konrad Gryczan, PhD:
import pandas as pd
import itertools
path = "CH-127 Add Index Column.xlsx"
input = pd.read_excel(path, usecols="B:C", skiprows=1, nrows=12)
test = pd.read_excel(path, usecols="E:G", skiprows=1, nrows=12).rename(columns=lambda x: x.replace('.1', ''))
input = input.sort_values(by='Stock')
input["diff"] = input.groupby('Stock')['Price'].diff().fillna(0)
input["group"] = (input["diff"] < 0).cumsum()
input["index"] = input.groupby(['Stock', 'group']).cumcount() + 1
input = input.sort_index()
input = input.drop(columns=["diff", "group"])
print(input.equals(test)) # True

Solving the challenge of Add Index Column! Part 4 with Python in Excel

Python in Excel solution 1 for Add Index Column! Part 4, proposed by Alejandro Campos:
df = xl("B2:C13", headers=True)
last_price, index_counter = {}, {}
for i, (stock, price) in df[['Stock', 'Price']].iterrows():
 if stock not in last_price or price < last_price[stock]:
 index_counter[stock] = 1
 else:
 index_counter[stock] += 1
 last_price[stock] = price
 df.at[i, 'Index'] = index_counter[stock]
df

Solving the challenge of Add Index Column! Part 4 with R

R solution 1 for Add Index Column! Part 4, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "files/CH-127 Add Index Column.xlsx"
input = read_excel(path, range = "B2:C13")
test = read_excel(path, range = "E2:G13")
compute_index <- function(price_vector) {
 idx <- rep(1, length(price_vector))
 for (i in 2:length(price_vector)) {
 if (price_vector[i] > price_vector[i - 1]) {
 idx[i] <- idx[i - 1] + 1
 } else {
 idx[i] <- 1
 }
 }
 return(idx)
}
result <- input %>%
 group_by(Stock) %>%
 mutate(index = compute_index(Price))
all.equal(result$index, test$index, check.attributes = FALSE)
#> [1] TRUE

Solving the challenge of Add Index Column! Part 4 with Google Sheets

Google Sheets solution 1 for Add Index Column! Part 4, proposed by Peter Krkos:
PowerQuery Solution:
https://docs.google.com/spreadsheets/d/1zR5IZLz8OT76vhaPEHfsPrw8-RDKnLyyqS49IJjdhFk/edit?gid=21319326#gid=21319326

Leave a Reply