SUMMARIZE

SUMMARIZE(tbl,tbl_hdrs,groupby_idxs,val_idxs,agg_fn_idxs)
tbl
a reference to an Excel table, or suitable array
tbl_hdrs
a reference to [#Headers] for tbl, or a headers for a data in tbl
groupby_idxs
a number or 1-d array of numbers for columns to group by
val_idxs
a number or 1-d array of numbers for columns to apply aggregation to
agg_fn_idxs
a number or 1-d array of numbers corresponding to AGGREGATE function_num; can also be custom function

Summarizes data table by grouping selected columns and aggregating.

tboulden

Board Regular
Joined
Jan 14, 2021
Messages
73
Office Version
  1. 365
Platform
  1. Windows
Meant to correspond loosely to DAX function SUMMARIZE; creates a tabular summary of a data table based upon chosen column attributes.

Excel Formula:
=LAMBDA(
  tbl,          // Table reference
  tbl_hdrs,     // Table1[#Headers], needed if tbl is from FILTER
  groupby_idxs, // = # or {#,#,#,...}, 1-D
  val_idxs,     // = # or {#,#,#,...}, 1-D
  agg_fn_idxs,  // = #, {#,#,#,...}, 1-D, or custom functions
    /* Custom function layout:
      LAMBDA(sw,
        SWITCH(sw,
          "label","Example Agg of",
          "function",LAMBDA(vals,fn(vals))
        )
      ) */
  LET(
    // Step 1a - Sequence rel idxs
    rel_idxs,SEQUENCE(,COLUMNS(groupby_idxs)),
    // Step 1b - Select attr cols from tbl
    attr_cols,pickCol(tbl,groupby_idxs),
    // Step 1c - Sort unique attr combinations
    sort_uniq_attrs,SORT(UNIQUE(attr_cols),rel_idxs),
    // Step 2a - Make an array of thunked attr tests
    attr_test_thunks,
      MAKEARRAY(
        ROWS(sort_uniq_attrs),
        COLUMNS(sort_uniq_attrs),
        LAMBDA(i,j,
          thunkIt(
            ifAnyOf(
              pickCol(attr_cols,j),
              isEqualTo(
                INDEX(sort_uniq_attrs,i,j)
              ))))),
    // Step 2b - Accumulate attribute tests by row
    accum_attr_tests,
      BYROW(
        attr_test_thunks,
        LAMBDA(row_,
          thunkIt(
            REDUCE(
              TRUE,
              row_,
              LAMBDA(acc_bool,col_thunk,
                acc_bool*col_thunk()
              ))))),
    // Step 2c - Map an array of thunked val cols
    val_col_thunks,
      MAP(val_idxs,
        LAMBDA(idx,
          thunkIt(
            pickCol(tbl,idx)
          ))),
    // Step 2d - Map an array of agg functions
    agg_funcs,
      MAP(agg_fn_idxs,aggHelper("function")),
    // Step 2e - Pairwise application of tests to cols
    tested_vals,
      pairWise(
        accum_attr_tests,
        val_col_thunks,
        LAMBDA(test,thunk,
          thunkIt(
            IF(test(),thunk(),"")
          ))),
    // Step 2f - Map agg funcs by row
    aggregated_vals,
      MAP(
        CHOOSE(SEQUENCE(ROWS(tested_vals),1,1,0),
          agg_funcs),
        tested_vals,
        LAMBDA(func,thunk,
          func(thunk())
        )),
    
        // Step 3 - Helper function
    getTblHdr,
      LAMBDA(hdr_ref,idxs,
        INDEX(hdr_ref,1,idxs)),
    // Step 3a - Row headers
    row_hdrs,getTblHdr(tbl_hdrs,groupby_idxs),
    // Step 3b - Val headers
    val_hdrs,getTblHdr(tbl_hdrs,val_idxs),
    // Step 3c - Aggregation label
    agg_labels,
      MAP(agg_fn_idxs,
        aggHelper("label"))&val_hdrs,
    
    // Step 4a - Stack attr hdrs and labels
    attr_hdrs_and_labels,
      vStack(row_hdrs,sort_uniq_attrs),
    // Step 4b - Stack agg labels and agg vals
    agg_labels_and_vals,
      vStack(agg_labels,aggregated_vals),
    // Step 4c - Stack side-by-side
    final,
      hStack(
        attr_hdrs_and_labels,
        agg_labels_and_vals),
    final    
  )
)

Has a few helper functions:
pickCol
Excel Formula:
=LAMBDA(tbl,idxs,
      INDEX(tbl,SEQUENCE(ROWS(tbl)),idxs))

aggHelper
Excel Formula:
=LAMBDA(lbl_or_agg,
    LAMBDA(idx_or_func,
      LET(
          lbls,{"AVERAGE of ","COUNT of ","COUNTA of ",
              "MAX of ","MIN of ","PRODUCT of ",
              "STDEV.S of ","STDEV.P of ","SUM of ",
              "VAR.S of ","VAR.P of ","MEDIAN of ","MODE.SNGL of "},
          SWITCH(lbl_or_agg,
            "label",
              IF(
                ISNUMBER(idx_or_func),INDEX(lbls,idx_or_func),
                idx_or_func("label")
              ),
             "function",
              IF(
                ISNUMBER(idx_or_func),
                  LAMBDA(vals,
                    LET(
                      filtered,
                        FILTER(vals,
                          NOT(ifAnyOf(vals, isEqualTo(0)))*
                          NOT(ifAnyOf(vals, isEqualTo("")))),
                      CHOOSE(idx_or_func,
                        AVERAGE(filtered),
                        COUNT(filtered),
                        COUNTA(filtered),
                        MAX(filtered),
                        MIN(filtered),
                        PRODUCT(filtered),
                        STDEV.S(filtered),
                        STDEV.P(filtered),
                        SUM(filtered),
                        VAR.S(filtered),
                        VAR.P(filtered),
                        MEDIAN(filtered),
                        MODE.SNGL(filtered)                  
                      )
                    )
                  ),
                LAMBDA(vals,idx_or_func("function")(
                  FILTER(vals,
                    NOT(ifAnyOf(vals, isEqualTo(0)))*
                    NOT(ifAnyOf(vals, isEqualTo(""))))))
              )
          )
      )
  )
)

References pairWise, thunkIt, and ifAnyOf and some of its helpers.
 
Upvote 0
Thanks to Contextures for the sample data of hockey players; table name is "PlayerData". Excel piivot tables have red header rows, my functions are below them.

LAMBDA_pairwise_thunks_summarize_pivot.xlsx
ABCDEFGHI
1IdxHeaderTeamCountryCount of NameLAverage of WeightAverage of HeightFt
21IDMenCanada25193.166.006666667
32TeamMenUSA251915.976666667
43CountryWomenCanada23152.86956525.630434783
54NameFWomenUSA23148.86956525.514492754
65NameL
76WeightTeamCountryCOUNTA of NameLAVERAGE of WeightAVERAGE of HeightFt
87HeightMenCanada25193.166.006666667
98DOBMenUSA251915.976666667
109HometownWomenCanada23152.86956525.630434783
1110ProvWomenUSA23148.86956525.514492754
1211Pos
1312AgeCountryTeamPosMin of HeightFtAverage of HeightFtMax of HeightFt
1413HeightFtCanadaMenDefence5.755.9895833336.25
1514HtInCanadaMenForward5.6666666675.9880952386.25
1615BMICanadaMenGoalie6.0833333336.1388888896.166666667
17CanadaWomenDefence5.3333333335.5416666675.75
18CanadaWomenForward5.4166666675.6547619055.833333333
19CanadaWomenGoalie5.6666666675.6944444445.75
20USAMenDefence5.756.0520833336.333333333
21USAMenForward5.5833333335.9226190486.416666667
22USAMenGoalie66.0277777786.083333333
23USAWomenDefence5.0833333335.5119047626
24USAWomenForward5.1666666675.5128205135.916666667
25USAWomenGoalie5.4166666675.5277777785.583333333
26
27CountryTeamPosMIN of HeightFtAVERAGE of HeightFtMAX of HeightFt
28CanadaMenDefence5.755.9895833336.25
29CanadaMenForward5.6666666675.9880952386.25
30CanadaMenGoalie6.0833333336.1388888896.166666667
31CanadaWomenDefence5.3333333335.5416666675.75
32CanadaWomenForward5.4166666675.6547619055.833333333
33CanadaWomenGoalie5.6666666675.6944444445.75
34USAMenDefence5.756.0520833336.333333333
35USAMenForward5.5833333335.9226190486.416666667
36USAMenGoalie66.0277777786.083333333
37USAWomenDefence5.0833333335.5119047626
38USAWomenForward5.1666666675.5128205135.916666667
39USAWomenGoalie5.4166666675.5277777785.583333333
summarize
Cell Formulas
RangeFormula
A2:B16A2=CHOOSE({1,2},SEQUENCE(COLUMNS(PlayerData[#Headers])),TRANSPOSE(PlayerData[#Headers]))
D7:H11D7=summarize(PlayerData,PlayerData[#Headers],{2,3},{5,6,13},{3,1,1})
D27:I39D27=summarize(PlayerData,PlayerData[#Headers],{3,2,11},{13,13,13},{5,1,4})
Dynamic array formulas.
 
And here's the formula with comments stripped out.
Excel Formula:
=LAMBDA(tbl,tbl_hdrs,groupby_idxs,val_idxs,agg_fn_idxs,
  LET(
    rel_idxs,SEQUENCE(,COLUMNS(groupby_idxs)),
    attr_cols,pickCol(tbl,groupby_idxs),
    sort_uniq_attrs,SORT(UNIQUE(attr_cols),rel_idxs),

    attr_test_thunks,
      MAKEARRAY(
        ROWS(sort_uniq_attrs),
        COLUMNS(sort_uniq_attrs),
        LAMBDA(i,j,
          thunkIt(
            ifAnyOf(
              pickCol(attr_cols,j),
              isEqualTo(
                INDEX(sort_uniq_attrs,i,j)
              ))))),
    accum_attr_tests,
      BYROW(
        attr_test_thunks,
        LAMBDA(row_,
          thunkIt(
            REDUCE(
              TRUE,
              row_,
              LAMBDA(acc_bool,col_thunk,
                acc_bool*col_thunk()
              ))))),
    val_col_thunks,
      MAP(val_idxs,
        LAMBDA(idx,
          thunkIt(
            pickCol(tbl,idx)
          ))),
    agg_funcs,
      MAP(agg_fn_idxs,aggHelper("function")),
    tested_vals,
      pairWise(
        accum_attr_tests,
        val_col_thunks,
        LAMBDA(test,thunk,
          thunkIt(
            IF(test(),thunk(),"")
          ))),
    aggregated_vals,
      MAP(
        CHOOSE(SEQUENCE(ROWS(tested_vals),1,1,0),
          agg_funcs),
        tested_vals,
        LAMBDA(func,thunk,
          func(thunk())
        )),

    getTblHdr,
      LAMBDA(hdr_ref,idxs,
        INDEX(hdr_ref,1,idxs)),

    row_hdrs,getTblHdr(tbl_hdrs,groupby_idxs),
    val_hdrs,getTblHdr(tbl_hdrs,val_idxs),
    agg_labels,
      MAP(agg_fn_idxs,
        aggHelper("label"))&val_hdrs,
    attr_hdrs_and_labels,
      vStack(row_hdrs,sort_uniq_attrs),
    agg_labels_and_vals,
      vStack(agg_labels,aggregated_vals),

    final,
      hStack(
        attr_hdrs_and_labels,
        agg_labels_and_vals),
    final
  )
)
 

Forum statistics

Threads
1,224,836
Messages
6,181,252
Members
453,028
Latest member
letswriteafairytale

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top