Aggregate
New to Analytica 4.2
Aggregate( X,map : Array[I] ; I, targetIndex : Index )
Aggregate converts an array «X» indexed by a fine-grained index «I» (e.g., Months) into an array indexed by a coarser index «targetIndex» (e.g., Years), by aggregating all the elements that map to the same «targetIndex» value. The «map» parameter specifies how the elements of «I» map to the elements of «targetIndex». Each cell of «map» should be an element of «targetIndex» (or, if you also specify an optional positional:true parameter, then each element of «map» can specify an integer position along «targetIndex»).
In its standard usage, Aggregate sums all elements from «X» that map to the same element along «targetIndex». However, the type of aggregation can be changed using an optional «type» parameter, containing the name of or handle to any valid aggregation function, such as Max, Min, Product, Average or Median.
Library
Array functions
Examples
Index Months := Sequence(MakeDate(2009,1,1),MakeDate(2020,1,1),dateUnit:"M") Index Years := 2009..2020 MonthsToYears := DatePart(Months,"Y") Revenue_by_month := { array indexed by Months } Revenue_by_year := Aggregate(Revenue_by_month,MonthsToYears,Months,Years)
Aggregation types
The optional «type» parameter specifies the aggregation type. The parameter names an existing array-reducing function, either built-in or user-defined. You can supply either the textual name of the function, or a handle to the function (or even an array to these). Built-in functions that can be applied include Sum (default), Max, Min, Average or Mean, Product, Median, SDeviation, Variance, Skewness, Kurtosis, and Join.
Revenue_dev := Aggregate(Revenue_by_month,MonthToYear,Month,Year,Type:"SDeviation") Peak_revenue:= Aggregate(Revenue_by_month,MonthToYear,Month,Year,Type:Handle(Max)) Ave_revenue := Aggregate(Revenue_by_month,MonthToYear,Month,Year,Type:"Average")
You can also create your own custom aggregation method in the form of a User-Defined Function. The function should accept an array parameter and an index, and should reduce the array so that the result eliminates the indicated index.
The following would all be examples of legal aggregation functions:
Function First(A:Array[I] ; I:Index) := A[@I=1] Function Last(A:Array[I] ; I:Index) := A[@I=Size(I)] Function Middle(A:Array[I] ; I:Index) := A[@I=Floor(Size(I)/2)+1] Function Count(A:Array[I] ; I:Index) := Size(I) Function PosMax(A:Array[I] ; I:Index) := ArgMax(A,I,position:true)
These would be used in the same fasion as other types:
Opening_Revenue := Aggregate(Revenue_by_month,MonthToYear,Month,Year,Type:"First") Closing_Revenue := Aggregate(Revenue_by_month,MonthToYear,Month,Year,Type:"Last") Best_Month := Aggregate(Revenue_by_month,MonthToYear,Month,Year,Type:Handle(PosMax))
Note: Aggregation (aka conglomeration) functions can also be utilized by the MdTable function. The requirements are the same.
Positional Maps
The «map» parameters to specifies how each element in the original index «I» maps into the «targetIndex». This is usually a many-to-one mapping. Your «map» is necessarily indexed by «I», and each element of «map» specifies an element of «targetIndex». When specifying the target values, you can do so either by value or by position. The default assumes that map contains values from «targetIndex», but by specifying the optional «positional» parameter as true, «map» is interpreted as containing positions.
Variable M_to_Y_pos := Floor( (@Month-1)/12 ) + 1 Variable Annual_Rev := Aggregate(Revenue_by_month,M_to_Y_pos,Month,Year,positional:true)
The «map» may contain Null values. With a positional mapping, any «I»-position in which «map» is Null does not get included in the aggregated result. With a value-based mapping, these elements are included only if one of the elements of «targetIndex» is «null» (which is uncommon).
Default Value
It is possible that no data maps to a particular value/position in «targetIndex». This can occur when that value (or position) never occurs within «map», or when all data in «X» that would map to that position is Null-valued. (Note: Aggregate ignores null values in «X»).
For result cells with no data, «null» is returned. No warning is issued when there are result cells with no data. If you'd like to use a different value, such as 0, you can specify the value in the optional «defaultValue» parameter, e.g.:
Aggregate(X,map,I,J,type:"SDeviation",defaultValue:0)
Inverses of Aggregate
Since Aggregate is used to map data from a finer-grained index to a coarser-grained index, it is natural to ask how the inverse is accomplished -- namely, mapping from a coarse-grained index to a fine-grain index.
Just as with aggregate, there are many potential types of de-aggregation. For example, when de-aggregating annual data down to months, we might use the annual value for every month in that year, or split it uniformly among all the target months, or perhaps assign it to only one month, using zero for all other months in that year.
The following uses the annual value for every month in that year. In the example, Annual_val is indexed by Year, while the result is indexed by Month:
Annual_val[ Year = MonthToYear ]
To spread the value uniformly across all months, we can do this:
Var MonthsPerYear := Aggregate(1,MonthToYear,Month,Year); Annual_val[ Year = MonthToYear ] / MonthsPerYear
See Also
- Subscript-Slice Operator -- standard reindexing
- Frequency -- basically aggregation with "count" type
- MdTable -- another function that accepts an aggregation/conglomeration parameter
Enable comment auto-refresher