Home » Hierarchical Project Indexing

Hierarchical Project Indexing

Do the Indexing for project, task and activity. Task indexing needs to be done for combination of Project & Task. Activity indexing needs to be done for combination of project, Task & activity.

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

Solving the challenge of Hierarchical Project Indexing with Power Query

Power Query solution 1 for Hierarchical Project Indexing, proposed by Zoran Milokanović:
let
  Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content], 
  F = (p, t, r) => Text.Combine({p, Text.From(Table.PositionOf(Table.Distinct(t), r) + 1)}, "."), 
  P = Table.AddColumn(
    Source, 
    "Project_Index", 
    each F(null, Source[[Project]], [Project = [Project]])
  ), 
  T = Table.AddColumn(
    P, 
    "Task_Index", 
    each F(
      [Project_Index], 
      Table.SelectRows(Source, (r) => r[Project] = [Project])[[Task]], 
      [Task = [Task]]
    )
  ), 
  A = Table.AddColumn(
    T, 
    "Activity_Index", 
    each F(
      [Task_Index], 
      Table.SelectRows(Source, (r) => r[Project] = [Project] and r[Task] = [Task])[[Activity]], 
      [Activity = [Activity]]
    )
  )
in
  A
Power Query solution 2 for Hierarchical Project Indexing, proposed by Kris Jaganah:
let
  A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  B = Table.AddIndexColumn(A, "I"), 
  C = Table.AddColumn(B, "Project_Index", each Character.ToNumber([Project]) - 64), 
  D = Table.AddColumn(
    C, 
    "Task_Index", 
    each [Project_Index] + (Character.ToNumber(Text.End([Task], 1)) - 64) / 10
  ), 
  E = Table.Group(
    D, 
    {"Task"}, 
    {
      "All", 
      (x) =>
        Table.AddColumn(
          x, 
          "Activity_Index", 
          each Text.From([Task_Index])
            & "."
            & Text.From(List.PositionOf(List.Distinct(x[Activity]), [Activity]) + 1)
        )
    }
  )[All], 
  F = Table.Combine(E), 
  G = Table.Sort(F, {"I", 0}), 
  H = Table.RemoveColumns(G, {"I"})
in
  H
Power Query solution 3 for Hierarchical Project Indexing, proposed by Abdallah Ally:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  AddColumn = Table.AddColumn(
    Source, 
    "Data", 
    each [
      a = Text.From(List.PositionOf(List.Distinct(Source[Project]), [Project]) + 1), 
      b = Table.SelectRows(Source, (x) => x[Project] = [Project])[Task], 
      c = Text.From(List.PositionOf(List.Distinct(b), [Task]) + 1), 
      d = Table.SelectRows(Source, (x) => x[Project] = [Project] and x[Task] = [Task])[Activity], 
      e = Text.From(List.PositionOf(List.Distinct(d), [Activity]) + 1), 
      f = Text.Combine({a, Text.Combine({a, c}, "."), Text.Combine({a, c, e}, ".")}, ", ")
    ][f]
  ), 
  Columns = List.Transform(Table.ColumnNames(Source), each _ & "_Index"), 
  Result = Table.SplitColumn(AddColumn, "Data", each Text.Split(_, ", "), Columns)
in
  Result
Power Query solution 4 for Hierarchical Project Indexing, proposed by Eric Laforce:
let
  fxAddIndex = (t as table, cNames as list) =>
    let
      cn = cNames{0}, 
      lastIdx = List.Last(List.Select(Table.ColumnNames(t), each Text.EndsWith(_, "_Index"))), 
      prefix = if (lastIdx = null) then "" else Table.Column(t, lastIdx){0} & ".", 
      values = List.Distinct(Table.Column(t, cn)), 
      Add_Idx = Table.AddColumn(
        t, 
        cn & "_Index", 
        each prefix & Text.From(List.PositionOf(values, Record.Field(_, cn)) + 1)
      )
    in
      if (List.Count(cNames) > 1) then
        Table.Combine(Table.Group(Add_Idx, cn, {"G", each @fxAddIndex(_, List.Skip(cNames))})[G])
      else
        Add_Idx, 
  Source = Excel.CurrentWorkbook(){[Name = "tData221"]}[Content], 
  Result = fxAddIndex(Source, Table.ColumnNames(Source))
in
  Result
Power Query solution 5 for Hierarchical Project Indexing, proposed by Luke Jarych:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  AddedIndex = Table.AddIndexColumn(Source, "IndexCol", 0, 1, Int64.Type), 
  AddRank = Table.AddRankColumn(AddedIndex, "Project_Index", {"Project"}, [RankKind = 1]), 
  Grouped = Table.Group(
    AddRank, 
    {"Project"}, 
    {
      {
        "Count", 
        each 
          let
            a = Table.AddRankColumn(_, "Task_Index", {"Task"}, [RankKind = 1]), 
            b = Table.TransformColumns(
              a, 
              {"Task_Index", each Text.From(a{_}[Project_Index]) & "." & Text.From(_)}
            )
          in
            b
      }
    }
  )[Count], 
  Expand = Table.Combine(Grouped), 
  Sorted = Table.Sort(Expand, {{"IndexCol", Order.Ascending}}), 
  Grouped2 = Table.Group(
    Sorted, 
    "Task", 
    {
      {
        "Activities", 
        (a) =>
          Table.AddColumn(
            a, 
            "Activity_Index", 
            each Text.From([Task_Index])
              & "."
              & Text.From(List.PositionOf(List.Distinct(a[Activity]), [Activity]) + 1)
          )
      }
    }
  )[Activities], 
  Final = Table.RemoveColumns(Table.Sort(Table.Combine(Grouped2), "IndexCol"), "IndexCol")
in
  Final
Power Query solution 6 for Hierarchical Project Indexing, proposed by Sandeep Marwal:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  S1 = Table.Group(
    Source, 
    {"Project"}, 
    {
      {
        "Count", 
        each Table.AddIndexColumn(
          Table.Group(
            Table.Distinct(_[[Task], [Activity]]), 
            {"Task"}, 
            {{"Count", each Table.AddIndexColumn(Table.Distinct(_[[Activity]]), "AI", 1)}}
          ), 
          "TI", 
          1
        )
      }
    }
  ), 
  I1 = Table.AddIndexColumn(S1, "PI", 1, 1, Int64.Type), 
  S2 = Table.ExpandTableColumn(I1, "Count", {"Task", "Count", "TI"}, {"Task", "Count.1", "TI"}), 
  S3 = Table.ExpandTableColumn(S2, "Count.1", {"Activity", "AI"}, {"Activity", "AI"}), 
  S4 = Table.NestedJoin(
    Source, 
    {"Project", "Task", "Activity"}, 
    S3, 
    {"Project", "Task", "Activity"}, 
    "Table1 (3)", 
    JoinKind.LeftOuter
  ), 
  S5 = Table.AddIndexColumn(S4, "Index", 1, 1, Int64.Type), 
  S6 = Table.ExpandTableColumn(S5, "Table1 (3)", {"AI", "TI", "PI"}, {"AI", "TI", "Project Index"}), 
  S7 = Table.AddColumn(S6, "Task Index", each Text.From([Project Index]) & "." & Text.From([TI])), 
  S8 = Table.AddColumn(S7, "Activity Index", each [Task Index] & "." & Text.From([AI])), 
  S9 = Table.RemoveColumns(S8, {"AI", "TI", "Index"})
in
  S9

Solving the challenge of Hierarchical Project Indexing with Excel

Excel solution 1 for Hierarchical Project Indexing, proposed by Bo Rydobon 🇹🇭:
=LET(
    z,
    A2:C20,
    i,
    MID(
        DROP(
            REDUCE(
                N(
                    +TAKE(
                        z,
                        ,
                        1
                    )
                ),
                SEQUENCE(
                    COLUMNS(
                        z
                    )
                ),
                LAMBDA(
                    p,
                    c,
                    LET(
                        a,
                        TAKE(
                            p,
                            ,
                            -1
                        ),
                        b,
                        INDEX(
                            z,
                            ,
                            c
                        ),
                        HSTACK(
                            p,
                            a&"."&MAP(
                                a,
                                b,
                                LAMBDA(
                                    i,
                                    j,
                                    LET(
                                        x,
                                        FILTER(
                                            b,
                                            i=a
                                        ),
                                        XMATCH(
                                            j,
                                            UNIQUE(
                                                x
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    )
                )
            ),
            ,
            1
        ),
        3,
        9
    ),
    VSTACK(
        TOROW(
            A1:C1&{"";"_Index"}
        ),
        HSTACK(
            z,
            IFERROR(
                --i,
                i
            )
        )
    )
)
Excel solution 2 for Hierarchical Project Indexing, proposed by Julian Poeltl:
=LET(H,
    A1:C1,
    P,
    A2:A20,
    T,
    B2:B20,
    A,
    C2:C20,
    RC,
    CODE(
        RIGHT(
            A
        )
    )-64,
    TI,
    --MAP(
        T,
        LAMBDA(
            A,
            TEXTJOIN(
                ",",
                ,
                CODE(
                    MID(
                        A,
                        SEQUENCE(
                            2
                        ),
                        1
                    )
                )-64
            )
        )
    ),
    HSTACK(VSTACK(
        H,
        HSTACK(
            P,
            T,
            A
        )
    ),
    VSTACK(H&"_Index",
    HSTACK(CODE(
        P
    )-64,
    TI,
    SUBSTITUTE(
        TI,
        ",",
        "."
    )&"."&IF((RC>2)*(SCAN(0,
    IFNA((TI<>DROP(
        TI,
        1
    ))*(RC<>DROP(
        RC,
        1
    )),
    0),
    SUM)>0),
    1,
    RC)))))
Excel solution 3 for Hierarchical Project Indexing, proposed by Oscar Mendez Roca Farell:
=LET(
    s,
     ".",
     p,
     A2:A20,
     F,
     LAMBDA(
         a,
          b,
          DROP(
              REDUCE(
                  "",
                   UNIQUE(
                       a
                   ),
                   LAMBDA(
                       y,
                        j,
                        LET(
                            f,
                             FILTER(
                                 b,
                                  a=j
                             ),
                             VSTACK(
                                 y,
                                  XMATCH(
                                      f,
                                       UNIQUE(
                                           f
                                       )
                                  )
                             )
                        )
                   )
              ),
               1
          )
     ),
     x,
     XMATCH(
         p,
          UNIQUE(
              p
          )
     ),
     t,
     F(
         p,
          B2:B20
     ),
     c,
     F(
         B2:B20,
          C2:C20
     ),
     HSTACK(
         A1:C20,
          VSTACK(
              HSTACK(
                  A1:C1&"_Index"
              ),
               HSTACK(
                   x,
                    x&s&t,
                    x&s&t&s&c
               )
          )
     )
)
Excel solution 4 for Hierarchical Project Indexing, proposed by Eddy Wijaya:
=LET(
d,
    A2:C20,
    
l_c,
    UNIQUE(
        DROP(
            REDUCE(
                0,
                TAKE(
                    d,
                    ,
                    2
                ),
                LAMBDA(
                    a,
                    v,
                    VSTACK(
                        a,
                        MID(
                            v,
                            SEQUENCE(
                                LEN(
                                    v
                                )
                            ),
                            1
                        )
                    )
                )
            ),
            1
        )
    ),
    
d_bCol,
    CHOOSECOLS(
        d,
        2
    ),
    
f,
    LAMBDA(
        x,
        XMATCH(
            x,
            l_c,
            0
        )
    ),
    
a,
    f(
        TAKE(
            d,
            ,
            1
        )
    ),
    
b,
    --(f(
        LEFT(
            d_bCol,
            1
        )
    )&"."&f(
        RIGHT(
            d_bCol,
            1
        )
    )),
    
c,
    BYROW(
        TAKE(
            d,
            ,
            -1
        ),
        LAMBDA(
            r,
            XMATCH(
                r,
                UNIQUE(
                    FILTER(
                        TAKE(
            d,
            ,
            -1
        ),
                        d_bCol=OFFSET(
                            r,
                            ,
                            -1
                        )
                    )
                ),
                0
            )
        )
    ),
    
HSTACK(
    d,
    a,
    b,
    b&"."&c
))
Excel solution 5 for Hierarchical Project Indexing, proposed by Nonbow Wu:
=LET(
    
    da,
    A2:C20,
     tsk,
    INDEX(
        da,
        ,
        2
    ),
     act,
    INDEX(
        da,
        ,
        3
    ),
     b,
    64,
    
    ut,
    UNIQUE(
        tsk
    ),
    
    t_ndx,
    XLOOKUP(
        tsk,
        ut,
        CODE(
            LEFT(
                ut
            )
        )-b&"."&CODE(
            RIGHT(
                ut
            )
        )-b,
        ,
        0
    ),
    
    a_ndx,
    MAP(
        act,
        tsk,
        LAMBDA(
            a,
            t,
            MATCH(
                a,
                UNIQUE(
                    FILTER(
                        act,
                        tsk=t
                    )
                ),
                0
            )
        )
    ),
    
    VSTACK(
        HSTACK(
            A1:C1,
            A1:C1&"_Index"
        ),
        HSTACK(
            da,
            LEFT(
                t_ndx
            ),
            t_ndx,
            t_ndx&"."&a_ndx
        )
    )
)

Solving the challenge of Hierarchical Project Indexing with Python

Python solution 1 for Hierarchical Project Indexing, proposed by Konrad Gryczan, PhD:
import pandas as pd
import numpy as np
path = "PQ_Challenge_221.xlsx"
input = pd.read_excel(path, usecols="A:C", nrows=20)
test = pd.read_excel(path, usecols="E:J", nrows=20).rename(columns=lambda x: x.replace('.1', ''))
test["Task_Index"] = test["Task_Index"].astype(str)
input['Project_Index'] = (input['Project'].astype('category').cat.codes + 1).astype(np.int64)
input['Task_Index'] = (input['Project_Index'].astype(str) + "." +
 input.groupby('Project')['Task']
 .transform(lambda x: (x.astype('category').cat.codes + 1).astype(str)))
input['Activity_Index'] = (input['Task_Index'] + "." +
 input.groupby(['Project', 'Task'])['Activity']
 .transform(lambda x: (x.astype('category').cat.codes + 1).astype(str)))
print(input.equals(test))   # True
                    
                  
Python solution 2 for Hierarchical Project Indexing, proposed by Luke Jarych:
Python:
import pandas as pd
import xlwings as xw
import re
wb = xw.Book(r'PQ_Challenge_221.xlsx')
sh = wb.sheets[0]
table1 = sh.tables['Table1']
rng1 = sh.range(table1.range.address)
df = rng1.options(pd.DataFrame, header=True, index=False, numbers=float).value
df['Project_Index'] = df['Project'].rank(method='dense').astype(int).astype(str)
df['Task_Index'] = df.groupby('Project')['Task'].rank(method='dense').astype(int).astype(str)
df['Task_Index'] = df['Project_Index'] + '.' + df['Task_Index']
df['Activity_Index'] = df.groupby(['Project', 'Task'])['Activity'].rank(method='dense').astype(int).astype(str)
df['Activity_Index'] = df['Task_Index'] + '.' + df['Activity_Index']
                    
                &  

Solving the challenge of Hierarchical Project Indexing with Python in Excel

Python in Excel solution 1 for Hierarchical Project Indexing, proposed by Alejandro Campos:
def generate_indices(df):
 df['Project_Index'] = df.groupby('Project').ngroup() + 1
 df['Task_Index'] = df.groupby(['Project', 'Task']).ngroup() + 1
 df['Task_Index'] = df['Project_Index'].astype(str) + ',' + df.groupby('Project')['Task'].transform(lambda x: pd.factorize(x)[0] + 1).astype(str)
 df['Activity_Index'] = df.groupby(['Project', 'Task'])['Activity'].transform(lambda x: pd.factorize(x)[0] + 1)
 df['Activity_Index'] = df['Project_Index'].astype(str) + '.' + df['Task_Index'].str.split(',').str[1] + '.' + df['Activity_Index'].astype(str)
 final_df = df[['Project', 'Task', 'Activity', 'Project_Index', 'Task_Index', 'Activity_Index']]
 return final_df
df = xl("A1:C20", headers=True)
final_df = generate_indices(df)
final_df
                    
                  
Python in Excel solution 2 for Hierarchical Project Indexing, proposed by Ümit Barış Köse, MSc:
df = xl("A1:C20", headers=True)
project_index = df.groupby('Project').ngroup() + 1
task_index = df.groupby(['Project', 'Task']).ngroup() + 1
activity_index = df.groupby(['Project', 'Task', 'Activity']).ngroup() + 1
df['Project_Index'] = project_index
df['Task_Index'] = df.groupby('Project')['Task'].transform(lambda x: pd.factorize(x)[0] + 1)
df['Activity_Index'] = df.groupby(['Project', 'Task'])['Activity'].transform(lambda x: pd.factorize(x)[0] + 1)
df['Task_Index'] = df['Project_Index'].astype(str) + ';' + df['Task_Index'].astype(str)
df['Activity_Index'] = df['Project_Index'].astype(str) + '.' + df['Task_Index'].str.split(';').str[1] + '.' + df['Activity_Index'].astype(str)
final_df = df[['Project', 'Task', 'Activity', 'Project_Index', 'Task_Index', 'Activity_Index']]
final_df.columns = ['Project', 'Task', 'Activity', 'Project_Index', 'Task_Index', 'Activity_Index']
final_df
                    
                  

Solving the challenge of Hierarchical Project Indexing with R

R solution 1 for Hierarchical Project Indexing, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "Power Query/PQ_Challenge_221.xlsx"
input = read_excel(path, range = "A1:C20")
test = read_excel(path, range = "E1:J20")
result = input %>%
 mutate(Project_Index = as.numeric(as.factor(Project))) %>%
 mutate(Task_Index = as.numeric(paste0(Project_Index,".",as.numeric(as.factor(Task)))) , .by = Project) %>%
 mutate(Activity_Index = paste0(Task_Index,".", as.numeric(as.factor(Activity))), .by = c(Project, Task)) 
all.equal(result, test)
# [1] TRUE 
                    
                  

&&

Leave a Reply