Home » Align WBS Hierarchy Data

Align WBS Hierarchy Data

Today’s challenge is contributed by Ahmad Syawal Ramli. Align WBS data as shown.

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

Solving the challenge of Align WBS Hierarchy Data with Power Query

Power Query solution 1 for Align WBS Hierarchy Data, proposed by Kris Jaganah:
let
  A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  B = List.Transform(List.Distinct(List.Select(A[ID], (z) => z >= 0)), Text.From), 
  C = List.Accumulate(
    B, 
    A, 
    (x, y) =>
      [
        a = Table.AddColumn(
          x, 
          y, 
          each 
            if Number.From(Text.Select(Text.Split([WBS], "WBS_"){1}?, {"0" .. "9"}))
              = Number.From(y)
            then
              [WBS]
            else
              null
        ), 
        b = Table.FillDown(a, {y}), 
        c = Table.TransformColumns(b, {y, each if _ = null then "XXX" else _})
      ][c]
  ), 
  D = Table.SelectColumns(C, B)
in
  D
Power Query solution 2 for Align WBS Hierarchy Data, proposed by Vida Vaitkunaite:
let
  A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  ColNames = List.Transform(
    List.Select({List.Min(A[ID]) .. List.Max(A[ID])}, each _ >= 0), 
    Text.From
  ), 
  Custom = Table.AddColumn(
    A, 
    "Tbl", 
    each 
      let
        a = [ID] < 0, 
        b = if a then {"0"} else ColNames, 
        c = if a then List.Max(A[ID]) else List.Max(A[ID]) - [ID], 
        d = if a then {null} else List.Repeat({null}, [ID]) & {[WBS]} & List.Repeat({"XXX"}, c), 
        e = Table.Transpose(Table.FromColumns({d}, {"Col"}), b)
      in
        e
  ), 
  Combine = Table.Combine(Custom[Tbl]), 
  Final = Table.FillDown(Combine, ColNames)
in
  Final
Power Query solution 3 for Align WBS Hierarchy Data, proposed by Seokho MOON:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Rows = List.Accumulate(
    Table.ToRows(Source), 
    {{}}, 
    (a, v) =>
      a
        & (
          if v{0} < 0 then
            {List.Last(a)}
          else
            {List.FirstN(List.Last(a), Number.From(Text.At(v{1}, 4))) & {v{1}}}
        )
  ), 
  ColNames = List.Transform(List.Positions(List.Last(Rows)), each Text.From(_)), 
  Res = Table.FromList(List.Skip(Rows), each _, ColNames, "XXX")
in
  Res
Power Query solution 4 for Align WBS Hierarchy Data, proposed by Seokho MOON:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Rows = List.Accumulate(
    Table.ToRows(Source), 
    [D = 0, R = {{}}], 
    (a, v) => [
      D = List.Max({v{0}, a[D]}), 
      R = a[R]
        & (if v{0} < 0 then {List.Last(a[R])} else {List.FirstN(List.Last(a[R]), v{0}) & {v{1}}})
    ]
  ), 
  ColNames = List.Transform({0 .. Rows[D]}, each Text.From(_)), 
  Res = Table.FromList(List.Skip(Rows[R]), each _, ColNames, "XXX")
in
  Res
Power Query solution 5 for Align WBS Hierarchy Data, proposed by Peter Krkos:
PowerQuery solution:
 L = List.Buffer(Table.ToRows(Source)),
 Gen = List.Accumulate(List.Distinct(List.Select(Source[ID], (x)=> x >= 0)), {}, (s,c)=> s &
 { {c} & List.Transform({0..List.Count(L)-1}, (x)=>
 if L{x}{0} = c then L{x}{1} else
 if L{x}{0} >= c then null else
 if L{x}{0} > -1 and L{x}{0} < c then "XXX"
 else null )
 } ),
 ToTable = Table.PromoteHeaders(Table.FromColumns(Gen)),
 FilledDown = Table.FillDown(ToTable, Table.ColumnNames(ToTable))
in
 FilledDown
                    
                  

Solving the challenge of Align WBS Hierarchy Data with Excel

Excel solution 1 for Align WBS Hierarchy Data, proposed by Bo Rydobon 🇹🇭:
=IFNA(
    REDUCE(
        SEQUENCE(
            ,
            MAX(
                A2:A30
            )+1,
            0
        ),
        B2:B30,
        LAMBDA(
            a,
            v,
            LET(
                n,
                @+v:A30,
                VSTACK(
                    a,
                    IFS(
                        n<0,
                        TAKE(
                            a,
                            -1
                        ),
                        n,
                        HSTACK(
                            TAKE(
                                a,
                                -1,
                                n
                            ),
                            v
                        ),
                        1,
                        v
                    )
                )
            )
        )
    ),
    "XXX"
)
Excel solution 2 for Align WBS Hierarchy Data, proposed by John V.:
=DROP(REDUCE(0,
    SEQUENCE(
        1+MAX(
            A2:A30
        )
    )-1,
    LAMBDA(b,
    y,
    HSTACK(b,
    SCAN("XXX",
    B2:B30,
    LAMBDA(a,
    v,
    LET(i,
    @+A30:v,
    IFS(i=y,
    v,
    (i>0)*(i-1),
    b(
        SEQUENCE(
            ,
            1+b(
                9^9,
                i
            ),
            0
        ),
        i,
        DROP(
            B1:v,
            ,
            1
        )
    ))))),
    "XXX"),
    1)
Excel solution 3 for Align WBS Hierarchy Data, proposed by 🇰🇷 Taeyong Shin:
=LET(w,
    B2:B30,
    i,
    A2:A30,
    r,
    ROW(
        w
    ),
    s,
    SEQUENCE(
        ,
        6,
        0
    ),
    VSTACK(s,
    DROP(REDUCE(0,
    s,
    LAMBDA(a,
    v,
    HSTACK(a,
    IFNA(IFS(NOT((i
Excel solution 4 for Align WBS Hierarchy Data, proposed by Kris Jaganah:
=LET(a,B2:B30,b,SCAN("",a,LAMBDA(x,y,IF(LEFT(y)="W",y,x))),c,--LEFT(TEXTAFTER(b,"_")),f,TOROW(UNIQUE(c)),g,IFS(c=f,b,c
Excel solution 5 for Align WBS Hierarchy Data, proposed by Kris Jaganah:
=LET(a,
    MAX(
        A2:A30
    )+1,
    b,
    SEQUENCE(
        ,
        a,
        0
    ),
    c,
    B2:B30,
    d,
    IFERROR(
        IF(
            FIND(
                "WBS_"&b,
                c
            ),
            c
        ),
        ""
    ),
    VSTACK(b,
    DROP(REDUCE("",
    b+1,
    LAMBDA(v,
    w,
    HSTACK(v,
    SCAN("",
    INDEX(
        d,
        ,
        w
    ),
    LAMBDA(x,
    y,
    IFS((y<>""),
    y,
    (y="")*(x=""),
    "XXX",
    1,
    x)))))),
    ,
    1)))
Excel solution 6 for Align WBS Hierarchy Data, proposed by Timothée BLIOT:
=LET(
    A,
    SEQUENCE(
        ,
        6
    )-1,
    VSTACK(
        A,
        DROP(
            REDUCE(
                0,
                A,
                LAMBDA(
                    w,
                    v,
                    LET(
                        B,
                        SCAN(
                            0,
                            A2:A30,
                            LAMBDA(
                                y,
                                x,
                                IF(
                                    x=v,
                                    y+1,
                                    y
                                )
                            )
                        ),
                        HSTACK(
                            w,
                            IF(
                                B>0,
                                "WBS_"&v&IF(
                                    MAX(
                                        B
                                    )>1,
                                    CHAR(
                                        B+64
                                    ),
                                    ""
                                ),
                                "XXX"
                            )
                        )
                    )
                )
            ),
            ,
            1
        )
    )
)
Excel solution 7 for Align WBS Hierarchy Data, proposed by Oscar Mendez Roca Farell:
=DROP(REDUCE(,A1:A30,LAMBDA(i,x,LET(r,A1:x,IFNA(VSTACK(i,XLOOKUP(SEQUENCE(,LOOKUP(2^9,r/(r>=0))+1,0),r,DROP(B1:x,,1),,,-1)),"XXX")))),1)
Excel solution 8 for Align WBS Hierarchy Data, proposed by Md. Zohurul Islam:
=LET(
    a,
    A2:A30,
    b,
    B2:B30,
    
    d,
    TOROW(
        UNIQUE(
            IF(
                a<=0,
                0,
                a
            )
        )
    ),
    
    e,
    "WBS_"&d,
    
    f,
    IFERROR(
        SEARCH(
            e,
            b
        ),
        0
    ),
    
    g,
    IF(
        f,
        b,
        ""
    ),
    
    z,
    LAMBDA(
        w,
        SCAN(
            "",
            w,
            LAMBDA(
                p,
                q,
                IF(
                    q="",
                    p,
                    q
                )
            )
        )
    ),
    
    u,
    SEQUENCE(
        ,
        COUNT(
            d
        )
    ),
    
    h,
    DROP(
        REDUCE(
            "",
            u,
            LAMBDA(
                x,
                y,
                HSTACK(
                    x,
                    z(
                        CHOOSECOLS(
                            g,
                            y
                        )
                    )
                )
            )
        ),
        ,
        1
    ),
    
    i,
    IF(
        h="",
        "XXX",
        h
    ),
    
    j,
    VSTACK(
        d,
        i
    ),
    
    j
)
Excel solution 9 for Align WBS Hierarchy Data, proposed by Pieter de B.:
=LET(
    a,
    A2:A30,
    s,
    SEQUENCE(
        ,
        MAX(
            a
        )+1,
        0
    ),
    REDUCE(
        s,
        a,
        LAMBDA(
            a,
            b,
            VSTACK(
                a,
                XLOOKUP(
                    s,
                    A2:b,
                    DROP(
                        B2:b,
                        ,
                        1
                    ),
                    "xxx",
                    ,
                    -1
                )
            )
        )
    )
)
Excel solution 10 for Align WBS Hierarchy Data, proposed by Pieter de B.:
=LET(
    a,
    A2:A30,
    s,
    SEQUENCE(
        ,
        MAX(
            a+1
        ),
        0
    ),
    IF(
        s<=VSTACK(
            MAX(
                a
            ),
            SCAN(
                ,
                a,
                LAMBDA(
                    x,
                    y,
                    IF(
                        y<0,
                        x,
                        y
                    )
                )
            )
        ),
        REDUCE(
            s,
            a,
            LAMBDA(
                x,
                y,
                VSTACK(
                    x,
                    XLOOKUP(
                        s,
                        A2:y,
                        TAKE(
                            B2:y,
                            ,
                            -1
                        ),
                        "xxx",
                        ,
                        -1
                    )
                )
            )
        ),
        "xxx"
    )
)
Excel solution 11 for Align WBS Hierarchy Data, proposed by Ankur Sharma:
=TEXTSPLIT(
    
    TEXTJOIN(
        "-",
         ,
         B2,
        
        SCAN(
            B2,
             SEQUENCE(
                 COUNTA(
                     A3:A30
                 )
             ),
             LAMBDA(
                 a,
                  b,
                 
                 LET(
                     c,
                      INDEX(
                          A3:A30,
                           b
                      ),
                     
                     IF(
                         c < 0,
                          a,
                          TEXTJOIN(
                              ", ",
                               ,
                               B2,
                               XLOOKUP(
                                   SEQUENCE(
                                       c
                                   ),
                                    TAKE(
                          A3:A30,
                           b
                      ),
                                    TAKE(
                                        B3:B30,
                                         b
                                    ),
                                    ,
                                    ,
                                    -1
                               )
                          )
                     )
                 )
             )
        )
        
    ),
     ", ",
     "-",
     ,
     ,
     "XXX"
)
Excel solution 12 for Align WBS Hierarchy Data, proposed by JvdV -:
=REDUCE(
    SEQUENCE(
        ,
        MAX(
            A2:A30
        )+1
    )-1,
    B2:B30,
    LAMBDA(
        x,
        y,
        IFNA(
            VSTACK(
                x,
                XLOOKUP(
                    "_"&TAKE(
                        x,
                        1,
                        @MOD(
                            y:A30,
                            MAX(
                                x
                            )+1
                        )+1
                    )&"D*$",
                    B2:y,
                    B2:y,
                    ,
                    3,
                    -1
                )
            ),
            "XXX"
        )
    )
)

Solving the challenge of Align WBS Hierarchy Data with Python

Python solution 1 for Align WBS Hierarchy Data, proposed by Konrad Gryczan, PhD:
import pandas as pd
import numpy as np
path = "645 Align WBS Data.xlsx"
input = pd.read_excel(path, usecols="A:B", nrows=30)
test = pd.read_excel(path, usecols="E:J", nrows=30)
def process_data(input):
 for i in range(6):
 col = str(i)
 input[col] = np.where(input['WBS'].str.contains(f'WBS_{col}'), input['WBS'], np.nan)
 input[col] = input[col].ffill() if i == 0 else input.groupby(str(i - 1))[col].ffill()
 return input.fillna("XXX").drop(columns=['WBS', 'ID'])
result = process_data(input)
result.columns = test.columns
print(result.equals(test)) # True
                    
                  

Solving the challenge of Align WBS Hierarchy Data with Python in Excel

Python in Excel solution 1 for Align WBS Hierarchy Data, proposed by Alejandro Campos:
df, hierarchy, levels = xl("A1:B30", headers=True), [], {}
for _, r in df.iterrows():
 if r["ID"] != -1: levels = {k: v for k, v in {**levels, r["ID"]: r["WBS"]}.items() if k <= r["ID"]}
 hierarchy.append([levels.get(i, "XXX") for i in range(6)])
result_df = pd.DataFrame(hierarchy, columns=range(6))
                    
                  
Python in Excel solution 2 for Align WBS Hierarchy Data, proposed by Seokho MOON:
def WBS(x):
 res = [[]]
 for row in x.itertuples(index=False):
 if row[0] < 0:
 res += [res[-1]]
 else:
 res += [res[-1][: int(row[1][4])] + [row[1]]]
 res_df = pd.DataFrame(res[1:]).fillna("XXX")
 res_df.columns = [str(i) for i in range(res_df.shape[1])]
 return res_df
WBS(df)
                    
                  

Solving the challenge of Align WBS Hierarchy Data with R

R solution 1 for Align WBS Hierarchy Data, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "Excel/645 Align WBS Data.xlsx"
input = read_excel(path, range = "A1:B30")
test = read_excel(path, range = "E1:J30")
result = reduce(0:5, function(data, i) {
 col = as.character(i)
 data = data %>% 
 mutate(!!col := if_else(str_detect(WBS, paste0("WBS_", col)), WBS, NA_character_))
 
 data = if (i == 0) {
 data %>% fill(!!sym(col), .direction = "down")
 } else {
 data %>% group_by(!!sym(as.character(i - 1))) %>% 
 fill(!!sym(col), .direction = "down") %>% 
 ungroup()
 }
 data
}, .init = input) %>% 
 mutate(across(everything(), ~replace_na(.x, "XXX"))) %>% 
 select(-WBS, -ID)
all.equal(result, test, check.attributes = FALSE)
                    
                  

&&

Leave a Reply