Aggregated Custom Expression Functions
Summary
- Aggregated Custom Expression Functions work on an array of data and return a single value
- This allows users to create Functions that operate on multiple rows or an entire column
Developers are able to provide Custom Aggregation Expression Functions to AdapTableQL.
These are functions which operate against an array of data and return a single value.
Note
The array of data provided to the Expression is often a column name, but this does not have to be the case
Custom Expression Functions are defined in the customAggregatedFunctions property in Expression Options.
customAggregatedFunctions
Record<string, AggregatedExpressionFunction>Deep Dive
Anatomy of an Custom Aggregated Expression Function
Developer Guide
Defining a Custom Aggregated Expression Function
In this Guide we create 4 Custom Aggregated Expression Functions:
PRODUCT- a straightforwrd function that returns the product of a series of numbersSUMSQ- a straightforwrd function that Mimics SUMSQL in Excel, returning sum of squares of numbersRANK- returns the rank of a number in a list - leverages more advanced properties available in the Function definitionLARGE- returns the Kth biggest number in a list (where K is an input) - also leverages advanced Function definition properties
expressionOptions: {
customAggregatedFunctions: {
PRODUCT: {
initialValue: 1,
reducer: (context: AggregatedExpressionReducerContext) => {
return context.accumulator * context.currentValue;
},
description: 'Returns product of an array of values',
signatures: ['PRODUCT(numericVals: number[])'],
examples: ['PRODUCT([price])'],
},
SUMSQ: {
initialValue: 1,
reducer: (context: AggregatedExpressionReducerContext) => {
return context.accumulator + context.currentValue * 2;
},
description:
'Mimics SUMSQL in Excel - returning sum of squares of arguments',
signatures: ['SUMSQ(numericVals: number[])'],
examples: ['SUMSQ([price])'],
},
RANK: {
initialValue: [],
reducer: (context: AggregatedExpressionReducerContext) => {
if (context.currentValue != undefined) {
context.accumulator.push(context.currentValue);
}
return context.accumulator;
},
processAggregatedValue: (
context: AggregatedExpressionProcessAggValueContext
) => {
const sortedDataCollection = context.aggregatedValue.sort(
(firstValue: any, secondValue: any) => firstValue - secondValue
);
const rankMap = new Map<any, number>();
sortedDataCollection.forEach((value: any, index: any) => {
rankMap.set(value, index + 1);
});
return rankMap;
},
prepareRowValue: (
context: AggregatedExpressionPrepareRowValueContext
) => {
const aggregatedColumnId = context.aggColumnId;
const rowValue = context.adaptableApi.gridApi.getRawValueFromRowNode(
context.rowNode,
aggregatedColumnId
);
return context.aggregatedValue.get(rowValue) as number;
},
description: 'Mimics RANK in Excel; returns rank of a number in given list',
signatures: ['RANK([amount])'],
examples: ['RANK([amount])'],
},
LARGE: {
initialValue: [],
reducer: (context: AggregatedExpressionReducerContext) => {
if (context.currentValue != undefined) {
context.accumulator.push(context.currentValue);
context.accumulator.sort((a: any, b: any) => b - a);
}
return context.accumulator;
},
processAggregatedValue: (
context: AggregatedExpressionProcessAggValueContext
) => {
const k = context.args[0];
if (k == undefined || k <= 0 || k > context.rowNodes.length) {
console.log('Invalid K value for LARGE function: ', k);
return;
}
return context.aggregatedValue[k - 1];
},
description: 'Mimics LARGE in Excel; returns Kth largest number in list',
signatures: ['LARGE([price], K: number)'],
examples: ['LARGE([price], 4)'],
},
}Add the Custom Expression Function definition to the customAggregatedFunctions section in Expression Options
Each entry is of type Record with the key and value as follows:
- key is the custom Function's
name(by convention, it is in CAPITAL LETTERS - to make it more readable when used in an Expression) - value is the Function's definition (which is of type:
AggregatedExpressionFunction)
Use the initialValue property to set the start value for the aggregation
This function will be called for each value (typically a row) in the Column Data
The context object provided to the function includes:
accumulator- value returned by the previous call to the reducer function, or the initialValue if this is the first call. You return the new accumulator value from this functioncurrentValue- current value being processed in Column Dataindex- index of current value in the Column Data
Called after the reducer has processed all values / rows
Can be used to change result of reducer based on the values array (e.g. average = aggregated value / count)
The function context includes:
aggregatedValue- result of the reducerrowNodes- array of row nodes (if aggregation was grouped, this will be array of row nodes for the group)
Called for each row after the reducer and processAggregatedValue functions.
Can be used when each row has a different aggregated value (e.g. percentage = row value / aggregated value)
The function context inlucdes the current row node.
There are 3 properties that should be provided in order to help Users accessing the Function in the Expression Editor:
description: Explains what the Function doessignatures: Shows how the Function should be calledexamples: Small examples of Function in action
- This example creates the 4 Custom Aggregation Expression Functions in the Developer Steps above, and references them in various Calculated Columns:
PRODUCT: multiplies set of values - used inTotal Rating(product ofRatingColumn) &Ccy Rating(product ofRatinggrouped byCurrency)SUMSQ: return sum of squares of values - used inSum Sq Rating(operates onRatingColumn)LARGE: returns the K-th largest value in a data set - used in2nd largest amount(2nd largest value inAmountColumn)RANK: returns the rank of a number in a list of numbers - used inAmt Rank(ranks theAmountColumn)
- Note: both
LARGEandRANKrequire data sorting; however,RANKoutperformsLARGEby leveraging Adaptable's provided hooks to sort the data only once and then using a map for quick lookups, resulting in a significant performance boost
Expand to see the Custom Aggregation Functions provided
- Open the Expression Editor for the Calculated Columns to see the Expressions and the Aggregated Expression Functions
- Sort the
Amountcolumn to and note how the2nd Large AmtandRanking of Amountare both correct