Home » Allocate Amounts by Quarter Days

Allocate Amounts by Quarter Days

Divide the amount across quarters falling in between From and To Date. The division needs to be done on the basis of number of days in a quarter. The amount may have some rounding error.

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

Solving the challenge of Allocate Amounts by Quarter Days with Power Query

Power Query solution 1 for Allocate Amounts by Quarter Days, proposed by Zoran Milokanović:
let
  Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content], 
  D = (t, f) => Duration.Days(t - f) + 1, 
  S = Table.CombineColumns(
    Table.Group(
      Table.ExpandListColumn(
        Table.CombineColumns(
          Table.AddColumn(Source, "TD", each D([To Date], [From Date])), 
          {"From Date", "To Date"}, 
          each List.Transform(
            List.DateTimes(_{0}, D(_{1}, _{0}), Duration.From(1)), 
            each "Q" & Text.From(Date.QuarterOfYear(_)) & "-" & DateTime.ToText(_, "yy")
          ), 
          "Quarter"
        ), 
        "Quarter"
      ), 
      {"Store", "Quarter", "TD", "Amount"}, 
      {{"D", each Table.RowCount(_)}}
    ), 
    {"TD", "Amount", "D"}, 
    each _{2} / _{0} * _{1}, 
    "Amount"
  )
in
  S
Power Query solution 2 for Allocate Amounts by Quarter Days, proposed by Kris Jaganah:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Type = Table.TransformColumnTypes(Source,{{"From Date", type date}, {"To Date", type date}}),
Amt = Table.AddColumn(Type, "Amt", each [
a =[From Date],
b = [To Date],
c = Number.From( Duration.Days(b-a))+1 ,
d = List.Dates(a,c,hashtag#duration(1,0,0,0)),
e = [Amount]/c,
f = List.Distinct( List.Transform(d,Date.EndOfQuarter)),
g = List.RemoveLastN( List.Sort( List.Combine({{a},f,{b}})),1),
h = List.Numbers(1,List.Count(g)),
i = List.Transform(g, each Number.From(_) ),
j = List.Transform(h, each i{_}-i{_-1}  ),
k = List.Transform( List.Combine({{ List.First(j)+1},List.RemoveLastN( List.RemoveFirstN(j))}),each Text.From( Number.Round( _ * e))),
l =List.Distinct( List.Transform(g, each "Q"&Text.From (Date.QuarterOfYear(_))&"-"& Text.End( Text.From(Date.Year(_)),2))),
m = List.RemoveLastN( List.Transform(h, each l{_-1}&"%"&k{_-1}))][m]),
Keep = Table.SelectColumns(Amt,{"Store", "Amt"}),
Xpand = Table.ExpandListColumn(Keep, "Amt"),
Split = Table.SplitColumn(Xpand, "Amt", Splitter.SplitTextByDelimiter("%"), {"Quarter", "Amount"}),
ToNum = Table.TransformColumnTypes(Split,{{"Amount", Int64.Type}})
in
ToNum


                    
                  
          
Power Query solution 3 for Allocate Amounts by Quarter Days, proposed by Aditya Kumar Darak 🇮🇳:
let
 Source = Excel.CurrentWorkbook(){[ Name = "data" ]}[Content],
 Record = Table.AddColumn (
 Source,
 "R",
 each [
 F = Date.From ( [From Date] ),
 T = Date.From ( [To Date] ),
 TD = Number.From ( T - F ) + 1,
 G = List.Generate (
 () => [ a = - 1, c = F ],
 ( f ) => f[c] < Date.EndOfQuarter ( T ) + hashtag#duration ( 1, 0, 0, 0 ),
 ( f ) => [
 a = f[a] + 1,
 b = Date.StartOfQuarter ( Date.AddQuarters ( F, a ) ),
 c = Date.EndOfQuarter ( b ),
 d = Number.From ( List.Min ( { T, c } ) - List.Max ( { F, b } ) ),
 e = ( d + 1 ) * [Amount] / TD,
 g = Date.QuarterOfYear ( b ),
 h = Date.Year ( b )
 ],
 ( f ) => [
 Store = [Store],
 Qtr  = "Qtr-" & Text.From ( f[g] ) & " " & Text.From ( f[h] ),
 Amount = Int64.From ( f[e] )
 ]
 ),
 R = List.Skip ( G )
 ][R]
 ),
 Return = Table.FromRecords ( List.Union ( Record[R] ) )
in
 Return
                    
                  
          
Power Query solution 4 for Allocate Amounts by Quarter Days, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Sol = Table.Combine(
    Table.AddColumn(
      Source, 
      "A", 
      (y) =>
        let
          a = {Number.From(Date.From(y[From Date])) .. Number.From(Date.From(y[To Date]))}, 
          b = List.Transform(a, Date.From), 
          c = List.Transform(
            b, 
            each "Q" & Text.From(Date.QuarterOfYear(_)) & "-" & Text.End(Text.From(Date.Year(_)), 2)
          ), 
          d = List.Transform(
            List.Distinct(c), 
            each {
              y[Store], 
              _, 
              Number.Round(List.Count(List.Select(c, (x) => x = _)) * y[Amount] / List.Count(b))
            }
          ), 
          e = Table.FromRows(d, {"Store", "Quarter", "Amount"})
        in
          e
    )[A]
  )
in
  Sol
Power Query solution 5 for Allocate Amounts by Quarter Days, proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  A = Table.TransformColumnTypes(
    Source, 
    {{"Store", type text}, {"From Date", type date}, {"To Date", type date}, {"Amount", Int64.Type}}
  ), 
  B = Table.AddColumn(A, "Dl", each {Number.From([From Date]) .. Number.From([To Date])}), 
  C = Table.AddColumn(B, "APD", each [Amount] / List.Count([Dl])), 
  D = Table.SelectColumns(C, {"Store", "Dl", "APD"}), 
  E = Table.ExpandListColumn(D, "Dl"), 
  F = Table.TransformColumnTypes(E, {{"Dl", type date}, {"APD", type number}}), 
  G = Table.AddColumn(F, "Quarter", each Date.QuarterOfYear([Dl]), Int64.Type), 
  H = Table.TransformColumns(G, {{"Quarter", each "Q" & Text.From(_, "en-US"), type text}}), 
  I = Table.AddColumn(H, "YY", each Text.End(Text.From([Dl]), 2)), 
  J = Table.CombineColumns(
    I, 
    {"Quarter", "YY"}, 
    Combiner.CombineTextByDelimiter("-", QuoteStyle.None), 
    "Quarter.1"
  ), 
  K = Table.Group(
    J, 
    {"Store", "Quarter.1"}, 
    {{"Amount", each Number.Round(List.Sum([APD]), 0), type nullable number}}
  )
in
  K
Power Query solution 6 for Allocate Amounts by Quarter Days, proposed by Venkata Rajesh:
let
  Source = Data, 
  Dates = Table.AddColumn(
    Source, 
    "Dates", 
    each List.Transform({Number.From([From Date]) .. Number.From([To Date])}, each Date.From(_))
  ), 
  Expand = Table.ExpandListColumn(Dates, "Dates"), 
  Quarter = Table.AddColumn(
    Expand, 
    "Qtr", 
    each "Q"
      & Text.From(Date.QuarterOfYear([Dates]))
      & "-"
      & Text.End(Text.From(Date.Year([Dates])), 2)
  ), 
  Group = Table.Group(
    Quarter, 
    {"Store", "Qtr"}, 
    {
      {
        "Amount", 
        each [
          store = List.Min([Store]), 
          days  = Table.RowCount(_), 
          sdays = Table.RowCount(Table.SelectRows(Quarter, each [Store] = store)), 
          Amt   = Number.Round((days / sdays) * List.Min([Amount]))
        ][Amt], 
        Int64.Type
      }
    }
  )
in
  Group
Power Query solution 7 for Allocate Amounts by Quarter Days, proposed by Szabolcs Phraner:
let
  Source = ..., 
  QuarterFormatting = (D as date) =>
    let
      Q = "Q" & Text.From(Date.QuarterOfYear(D)), 
      Y = Date.ToText(D, [Format = "yy"])
    in
      Q & "-" & Y, 
  Generate_AmountsForPeiod = Table.TransformRows(
    Source, 
    (Row) =>
      List.Generate(
        () => Row[From Date], 
        each _ <= Row[To Date], 
        each Date.AddDays(_, 1), 
        each [
          Store   = Row[Store], 
          Quarter = QuarterFormatting(_), 
          Amount  = Row[Amount] / Duration.Days(Row[To Date] - Row[From Date])
        ]
      )
  ), 
  TableFromRec = Table.FromRecords(
    List.Combine(Generate_AmountsForPeiod), 
    type table [Store = text, Quarter = text, Amount = number]
  ), 
  GroupBy = Table.Group(
    TableFromRec, 
    {"Store", "Quarter"}, 
    {{"Amount", each List.Sum([Amount]), type number}}
  ), 
  Rounding = Table.TransformColumns(GroupBy, {{"Amount", each Number.Round(_, 0), type number}})
in
  Rounding

Solving the challenge of Allocate Amounts by Quarter Days with Excel

Excel solution 1 for Allocate Amounts by Quarter Days, proposed by Bo Rydobon 🇹🇭:
=REDUCE(F1:H1,
    D2:D4,
    LAMBDA(a,
    v,
    LET(b,
    @+v:B4,
    c,
    @+v:C4,
    
p,
    EOMONTH(
        b,
        FLOOR(
            MONTH(
                b
            )-1,
            3
        )-MONTH(
                b
            )
    ),
    q,
    EOMONTH(
        c,
        CEILING(
            MONTH(
                c
            ),
            3
        )-MONTH(
                c
            )
    ),
    
r,
    EOMONTH(
        p,
        SEQUENCE(
            YEARFRAC(
                p,
                q
            )*4
        )*3
    ),
    
VSTACK(a,
    CHOOSE({1,
    2,
    3},
    @+v:A4,
    "Q"&MONTH(
        r
    )/3&-RIGHT(
        YEAR(
        r
    ),
        2
    ),
    ROUND(MAP(
        r,
        LAMBDA(
            x,
            MIN(
                x,
                c
            )-MAX(
                EOMONTH(
                    x,
                    -3
                ),
                b-1
            )
        )
    )*v/(c-b+1),
    ))))))
Excel solution 2 for Allocate Amounts by Quarter Days, proposed by محمد حلمي:
=REDUCE(F1:H1,
    B2:B4,
    LAMBDA(a,
    d,
    LET(
e,
    TAKE(
        d:C4,
        1,
        -1
    ),
    i,
    @+d:A4,
    r,
    e-d+1,
    
j,
    SEQUENCE(
        r,
        ,
        d
    ),
    v,
    "Q"&INT((MONTH(
        j
    )-1)/3)+1&-RIGHT(
         YEAR(
        j
    ),
        2
    ),
    u,
    UNIQUE(
        v
    ),
    VSTACK(a,
    IFNA(HSTACK(i,
    u,
    ROUND(MAP(u,
    LAMBDA(c,
    SUM((c=v)*TAKE(
        d:D4,
        1,
        -1
    )/r))),
    )),
    i)))))
Excel solution 3 for Allocate Amounts by Quarter Days, proposed by محمد حلمي:
=REDUCE(F1:H1,
    B2:B4,
    LAMBDA(a,
    d,
    LET(
e,
    TAKE(
        d:C4,
        1,
        -1
    ),
    i,
    @+d:A4,
    r,
    e-d+1,
    
j,
    SEQUENCE(
        r,
        ,
        d
    ),
    v,
    "Q"&INT((MONTH(
        j
    )-1)/3)+1
&-RIGHT(
     YEAR(
        j
    ),
    2
),
    u,
    UNIQUE(
        v
    ),
    VSTACK(
        a,
        
        IFNA(
            HSTACK(
                i,
                u,
                ROUND(
                    MMULT(
                        XMATCH(
                            
                            u,
                            v,
                            ,
                            {1,
                            -1}
                        )*{-1,
                        1}+{0,
                        1},
                        {1;1}
                    )*TAKE(
                        d:D4,
                        1,
                        -1
                    )/r,
                    
                )
            ),
            i
        )
    ))))
Excel solution 4 for Allocate Amounts by Quarter Days, proposed by 🇰🇷 Taeyong Shin:
=REDUCE(
    F1:H1,
    D2:D4,
    LAMBDA(
        a,
        v,
        LET(
            s,
            @+B4:v,
            e,
            @+C4:v,
            d,
            VSTACK(
                EOMONTH(
                    s,
                    SEQUENCE(
                        CEILING(
                            YEARFRAC(
                                s,
                                e,
                                1
                            )*12,
                            1
                        ),
                        ,
                        0
                    )
                ),
                e
            ),
            r,
            "Q"&MONTH(
                MONTH(
                    d
                )*10
            )&-TEXT(
                d,
                "yy"
            ),
            VSTACK(
                a,
                DROP(
                    GROUPBY(
                        CHOOSE(
                            {1,
                            2,
                            3},
                            XMATCH(
                                r,
                                r
                            ),
                            @+A4:v,
                            r
                        ),
                        DROP(
                            VSTACK(
                                @d-s+1,
                                DROP(
                                    d,
                                    1
                                )-d
                            ),
                            -1
                        ),
                        LAMBDA(
                            a,
                            b,
                            ROUND(
                                v*PERCENTOF(
                                    a,
                                    b
                                ),
                                
                            )
                        )
                    ),
                    -1,
                    1
                )
            )
        )
    )
)
Excel solution 5 for Allocate Amounts by Quarter Days, proposed by Julian Poeltl:
=VSTACK(
    HSTACK(
        "Store",
        "Quarter",
        "Amount"
    ),
    LET(
        R,
        WRAPROWS(
            TEXTSPLIT(
                TEXTJOIN(
                    ",",
                    ,
                    BYROW(
                        A2:D4,
                        LAMBDA(
                            T,
                            LET(
                                A,
                                TAKE(
                                    T,
                                    ,
                                    1
                                ),
                                B,
                                INDEX(
                                    T,
                                    ,
                                    2
                                ),
                                C,
                                INDEX(
                                    T,
                                    ,
                                    3
                                ),
                                D,
                                TAKE(
                                    T,
                                    ,
                                    -1
                                ),
                                SQ,
                                SEQUENCE(
                                    C-B+1,
                                    ,
                                    B
                                ),
                                Q,
                                MAP(
                                    SQ,
                                    LAMBDA(
                                        E,
                                        MONTH(
                                            10*MONTH(
                                                E
                                            )
                                        )
                                    )
                                ),
                                Y,
                                YEAR(
                                    SQ
                                ),
                                QQ,
                                A&","&"Q"&Q&"-"&RIGHT(
                                    Y,
                                    2
                                ),
                                UQ,
                                UNIQUE(
                                    QQ
                                ),
                                CC,
                                MAP(
                                    UQ,
                                    LAMBDA(
                                        A,
                                        COUNTA(
                                            FILTER(
                                                QQ,
                                                QQ=A
                                            )
                                        )
                                    )
                                ),
                                Am,
                                CC/SUM(
                                    CC
                                )*D,
                                TEXTJOIN(
                                    ",",
                                    ,
                                    UQ&","&Am
                                )
                            )
                        )
                    )
                ),
       &         ","
            ),
            3
        ),
        IFERROR(
            R*1,
            R
        )
    )
)
Excel solution 6 for Allocate Amounts by Quarter Days, proposed by Duy Tùng:
=REDUCE(F1:H1,
    D2:D4,
    LAMBDA(x,
    y,
    LET(a,
    @+A4:y,
    b,
    @+B4:y,
    c,
    @+C4:y,
    g,
    SEQUENCE(
        c-b+1,
        ,
        b
    ),
    h,
    "Q"&INT((MONTH(
        g
    )-1)/3)+1&TEXT(
        g,
        "-yy"
    ),
    VSTACK(x,
    IFNA(HSTACK(a,
    DROP(GROUPBY(HSTACK(
        YEAR(
        g
    ),
        h
    ),
    h,
    LAMBDA(u,
    ROUND(ROWS(
        u
    )*y/(c-b+1),
    0)),
    ,
    0),
    ,
    1)),
    a)))))
Excel solution 7 for Allocate Amounts by Quarter Days, proposed by Sunny Baggu:
=REDUCE(
 HSTACK(
     A1,
      "Quarter",
      D1
 ),
    
 SEQUENCE(
     ROWS(
         A2:D4
     )
 ),
    
 LAMBDA(x,
     y,
    
 VSTACK(
 x,
    
 LET(
 _e1,
     LAMBDA(
         k,
          INDEX(
              A2:D4,
               y,
               k
          )
     ),
    
 _c1,
     _e1(1),
    
 _c2,
     _e1(2),
    
 _c3,
     _e1(3),
    
 _c4,
     _e1(4),
    
 _a,
     SEQUENCE(
         _c3 - _c2 + 1,
          ,
          _c2
     ),
    
 _q,
     ROUNDUP(
         MONTH(
             _a
         ) / 3,
          0
     ),
    
 _y,
     RIGHT(
         YEAR(
             _a
         ),
          2
     ),
    
 _uy,
     UNIQUE(
         _q & "-" & _y
     ),
    
 _v,
     MAP(
         
          _uy,
         
          LAMBDA(
              e,
              
               MROUND(
                   _c4 * ROWS(
                       FILTER(
                           _q,
                            _q & "-" & _y = e
                       )
                   ) / ROWS(
                       _q
                   ),
                    1
               )
               
          )
          
     ),
    
 IFNA(
     HSTACK(
         _c1,
          "Q" & _uy,
          _v
     ),
      _c1
 )
 )
 )
 )
)
Excel solution 8 for Allocate Amounts by Quarter Days, proposed by LEONARD OCHEA 🇷🇴:
=REDUCE(F1:H1,
    A2:A4,
    LAMBDA(a,
    b,
    LET(F,
    OFFSET,
    m,
    F(
        b,
        ,
        1
    ),
    n,
    F(
        b,
        ,
        2
    ),
    p,
    F(
        b,
        ,
        3
    ),
    d,
    n-m+1,
    s,
    SEQUENCE(
        d,
        ,
        m
    ),
    c,
    p/d/s^0,
    q,
    "Q"&INT((MONTH(
        s
    )-1)/3)+1&"-"&RIGHT(
        YEAR(
        s
    ),
        2
    ),
    u,
    UNIQUE(
        q
    ),
    z,
    ROUND(
        MMULT(
            N(
                TOROW(
        q
    )=u
            ),
            c
        ),
        0
    ),
    VSTACK(
        a,
        HSTACK(
            IF(
                z,
                b
            ),
            u,
            z
        )
    ))))


with INDEX ( without volatil OFFSET )

=LET(t,
    A2:D4,
    REDUCE(F1:H1,
    SEQUENCE(
        ROWS(
            t
        )
    ),
    LAMBDA(a,
    b,
    LET(I,
    LAMBDA(
        x,
        INDEX(
            t,
            b,
            x
        )
    ),
    m,
    I(
        2
    ),
    d,
    I(
        3
    )-m+1,
    s,
    SEQUENCE(
        d,
        ,
        m
    ),
    c,
    I(
        4
    )/d/s^0,
    q,
    "Q"&INT((MONTH(
        s
    )-1)/3)+1&"-"&RIGHT(
        YEAR(
        s
    ),
        2
    ),
    u,
    UNIQUE(
        q
    ),
    z,
    ROUND(
        MMULT(
            N(
                TOROW(
        q
    )=u
            ),
            c
        ),
        0
    ),
    VSTACK(
        a,
        HSTACK(
            IF(
                z,
                I(
                    1
                )
            ),
            u,
            z
        )
    )))))
Excel solution 9 for Allocate Amounts by Quarter Days, proposed by Abdallah Ally:
=LET(
    a,
    A2:A4,
    b,
    REDUCE(
        F1:H1,
        a,
        LAMBDA(
            x,
            y,
            LET(
                s,
                LAMBDA(
                    m,
                    n,
                     OFFSET(
                         m,
                         ,
                         n
                     )
                ),
                t,
                SEQUENCE(
                    s(
                        y,
                        2
                    )-s(
                        y,
                        1
                    )+1,
                    ,
                    s(
                        y,
                        1
                    )
                ),
                u,
                "Q"&ROUNDUP(
                     MONTH(
                         t
                     )/3,
                    0
                )&TEXT(
                    t,
                    "-yy"
                ),
                VSTACK(
                    x,
                    REDUCE(
                        "",
                        UNIQUE(
                            u
                        ),
                         LAMBDA(
                             p,
                             q,
                             VSTACK(
                                 p,
                                 HSTACK(
                                     y,
                                     q,
                                     ROUND(
                                         s(
                                             y,
                                             3
                                         )*COUNTA(
                                             FILTER(
                                                 u,
                                                 u=q
                                             )
                                         )/COUNTA(
                            u
                        ),
                                         0
                                     )
                                 )
                             )
                         )
                    )
                )
            )
        )
    ),
    FILTER(
        b,
        TAKE(
            b,
            ,
            1
        )<>""
    )
)
Excel solution 10 for Allocate Amounts by Quarter Days, proposed by 🇵🇪 Ned Navarrete C.:
=REDUCE(F1:H1,
    SEQUENCE(
        ROWS(
            A2:D4
        )
    ),
    LAMBDA(c,
    v,
    LET(e,
    LAMBDA(
        i,
        INDEX(
            A2:D4,
            v,
            i
        )
    ),
    f,
    SEQUENCE(
        e(
            3
        )-e(
            2
        )+1,
        ,
        e(
            2
        )
    ),
    q,
    "Q"&ROUNDUP(
        MONTH(
            f
        )/3,
        
    )&"-"&TEXT(
        f,
        "yy"
    ),
    u,
    UNIQUE(
        q
    ),
    d,
    MAP(
        u,
        LAMBDA(
            x,
            ROWS(
                FILTER(
                    f,
                    q=x
                )
            )
        )
    ),
    a,
    ROUND(e(
        4
    )*d/(e(
            3
        )-e(
            2
        )+1),
    ),
    VSTACK(
        c,
        IFNA(
            HSTACK(
                e(
                    1
                ),
                u,
                a
            ),
            e(
                    1
                )
        )
    ))))
Excel solution 11 for Allocate Amounts by Quarter Days, proposed by Tolga Demirci, PMP, PMI-ACP, MOS-Expert:
=HSTACK(DROP(
    TEXTSPLIT(
        TEXTJOIN(
            ,
            ,
            MAP(
                A2:A4,
                B2:B4,
                C2:C4,
                LAMBDA(
                    x,
                    y,
                    z,
                    TEXTJOIN(
                        ",",
                        ,
                        LET(
                            e,
                            SEQUENCE(
                                12,
                                ,
                                1,
                                1
                            ),
                            c,
                            SEQUENCE(
                                ,
                                z-y+1,
                                y,
                                1
                            ),
                            a,
                            MAP(
                                MONTH(
                                    c
                                ),
                                c,
                                LAMBDA(
                                    x,
                                    y,
                                    XLOOKUP(
                                        x,
                                        e,
                                        "Q"&ROUNDUP(
                                            e/3,
                                            0
                                        )
                                    )&"-"&YEAR(
                                        y
                                    )
                                )
                            ),
                            IF(
                                UNIQUE(
                                    TOCOL(
                                        a
                                    )
                                )<>"",
                                x,
                                ""
                            )
                        )
                    )
                )
            )&","
        ),
        ,
        ","
    ),
    -1
),
    DROP(
        TEXTSPLIT(
            TEXTJOIN(
                ,
                ,
                MAP(
                    B2:B4,
                    C2:C4,
                    LAMBDA(
                        m,
                        n,
                        TEXTJOIN(
                            ",",
                            ,
                            LET(
                                e,
                                SEQUENCE(
                                12,
                                ,
                                1,
                                1
                            ),
                                c,
                                SEQUENCE(
                                    ,
                                    n-m+1,
                                    m,
                                    1
                                ),
                                a,
                                MAP(
                                    MONTH(
                                    c
                                ),
                                    c,
                                    LAMBDA(
                                        x,
                                        y,
                                        XLOOKUP(
                                            x,
                                            e,
                                            "Q"&ROUNDUP(
                                            e/3,
                                            0
                                        )
                                        )&"-"&YEAR(
                                        y
                                    )
                                    )
                                ),
                                HSTACK(
                                    UNIQUE(
                                    TOCOL(
                                        a
                                    )
                                )
                                )
                            )
                        )
                    )
                )&","
            ),
            ,
            ","
        ),
        -1
    ),
    DROP(TEXTSPLIT(TEXTJOIN(,
    ,
    MAP(B2:B4,
    C2:C4,
    D2:D4,
    LAMBDA(k,
    l,
    h,
    TEXTJOIN(",",
    ,
    LET(e,
    SEQUENCE(
                                12,
                                ,
                                1,
                                1
                            ),
    c,
    SEQUENCE(
        ,
        l-k+1,
        k,
        1
    ),
    a,
    MAP(
        MONTH(
                                    c
                                ),
        c,
        LAMBDA(
            x,
            y,
            XLOOKUP(
                x,
                e,
                "Q"&ROUNDUP(
                                            e/3,
                                            0
                                        )
            )&"-"&YEAR(
                                        y
                                    )
        )
    ),
    MAP(UNIQUE(
                                    TOCOL(
                                        a
                                    )
                                ),
    LAMBDA(b,
    ROUND(SUM(FILTER(BYCOL(c,
    LAMBDA(d,
    IF(AND(
        d>=k,
        d<=l
    ),
    h/(l-k+1),
    0))),
    b=a)),
    0)))))))&","),
    ,
    ","),
    -1))
Excel solution 12 for Allocate Amounts by Quarter Days, proposed by Andres Rojas Moncada:
=REDUCE({"Store",
    "Quarter",
    "Amount"},
    D2:D4,
    LAMBDA(a,
    v,
    LET(ti,
    @+(A4:v),
    fi,
    @+(B4:v),
    ff,
    @+(C4:v),
    dif,
    ff-fi+1,
    d,
    RIGHT,
    fe,
    SEQUENCE(
        dif,
        ,
        fi
    ),
    rg,
    ti&"Q"&INT((MONTH(
        fe
    )-1)/3)+1&"-"&d(
        YEAR(
        fe
    ),
        2
    ),
    ag,
    GROUPBY(
        rg,
        rg,
        ROWS,
        0,
        0
    ),
    ct,
    TAKE(
        ag,
        ,
        1
    ),
    di,
    TAKE(
        ag,
        ,
        -1
    ),
    VSTACK(
        a,
        SORTBY(
            HSTACK(
                LEFT(
                    ct
                ),
                d(
                    ct,
                    5
                ),
                di*v/dif
            ),
            d(
                ct,
                2
            )
        )
    ))))

Solving the challenge of Allocate Amounts by Quarter Days with Python

Python solution 1 for Allocate Amounts by Quarter Days, proposed by Konrad Gryczan, PhD:
import pandas as pd
input = pd.read_excel("PQ_Challenge_188.xlsx", usecols="A:D", nrows=3)
test = pd.read_excel("PQ_Challenge_188.xlsx", usecols="F:H", nrows=11)
test.columns = test.columns.str.replace(".1", "")
result = input.assign(date=input.apply(lambda row: pd.date_range(row['From Date'], row['To Date'], freq='D'), axis=1)) 
 .explode('date') 
 .assign(days=lambda df: (df['To Date'] - df['From Date']).dt.days + 1) 
 .assign(daily=lambda df: df['Amount'] / df['days']) 
 .assign(quarter=lambda df: df['date'].dt.quarter) 
 .assign(year=lambda df: df['date'].dt.year.astype(str).str[2:4]) 
 .assign(Quarter=lambda df: 'Q' + df['quarter'].astype(str) + '-' + df['year']) 
 .groupby(['Store', 'Quarter', 'quarter', 'year']) 
 .agg(Amount=('daily', 'sum')) 
 .round(0) 
 .astype("int64") 
 .sort_values(by=['Store','year', 'quarter']) 
 .reset_index(drop=False) 
 .drop(columns=['quarter', 'year'])
print(result.equals(test)) # True
                    
                  

Solving the challenge of Allocate Amounts by Quarter Days with Python in Excel

Python in Excel solution 1 for Allocate Amounts by Quarter Days, proposed by Alejandro Campos:
df = xl("A1:D4", headers=True)
df = pd.concat(
 [pd.DataFrame({
 'Store': [row['Store']] * len(dates := pd.date_range(
 row['From Date'], row['To Date'])),
 'Date': dates,
 'Amount': [row['Amount']] * len(dates)
 }) for _, row in df.iterrows()], 
 ignore_index=True
)
df['Quarter'] = 'Q' + df['Date'].dt.quarter.astype(
 str) + '-' + df['Date'].dt.strftime('%y')
df['QrtC'] = df.groupby(['Store', 'Quarter'])['Store'].transform('size')
df['StrC'] = df.groupby('Store')['Store'].transform('size')
df['Amount'] = round(df['Amount'] * df['QrtC'] / df['StrC'])
df = df[['Store', 'Quarter', 'Amount']].drop_duplicates(ignore_index=True)
df
                    
                  
Python in Excel solution 2 for Allocate Amounts by Quarter Days, proposed by Abdallah Ally:
import pandas as pd
file_path = 'PQ_Challenge_188.xlsx'
df = pd.read_excel(file_path, usecols='A:D', nrows=3)
# Perform data wrangling
dfs = []
for i in df.index:
 date_range = pd.date_range(start=df.iat[i, 1], end=df.iat[i, 2])
 l = len(date_range)
 values = {'Store': [df.iat[i, 0]] * l,
 'Date': date_range,
 'ThisAmount': [df.iat[i, 3]] * l
 }
 dfs.append(pd.DataFrame(values))
df = pd.concat(dfs, ignore_index=True)
df['Quarter'] = df['Date'].map(lambda x: f"Q{x.quarter}-{x.strftime('%y')}")
df['QuarterCount'] = df.groupby(['Store', 'Quarter'])['Quarter'].transform('count')
df['StoreCount'] = df.groupby('Store')['Store'].transform('count')
df['Amount'] = df.apply(lambda x: round(x[2] * x[4] / x[5]), axis=1)
df = df.iloc[:, [0, 3, 6]].drop_duplicates(ignore_index=True)
df
                    
                  

Solving the challenge of Allocate Amounts by Quarter Days with R

R solution 1 for Allocate Amounts by Quarter Days, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
input = read_excel("Power Query/PQ_Challenge_188.xlsx", range = "A1:D4")
test = read_excel("Power Query/PQ_Challenge_188.xlsx", range = "F1:H11")
result = input %>%
 mutate(date = map2(`From Date`, `To Date`, seq, by = "day"), 
 days = map_int(date, length),
 daily = Amount / days) %>%
 unnest(date) %>%
 mutate(quarter = quarter(date), 
 year = year(date) %>% as.character() %>% str_sub(3, 4),
 Quarter = paste0("Q",quarter,"-",year)) %>%
 summarise(Amount = sum(daily) %>% round(0), .by = c(Store, Quarter))
identical(result, test)
# [1] TRUE
                    
                  

&

Leave a Reply