I’m trying to implement a custom aggregate function in Postgres which will average directions in degrees – i.e. I want to able to do:
SELECT circavg(direction) FROM sometable;
This can be done using the formula:
xbar = atan2(sum(sin(xi), sum(cos(xi)))
I think I need to define an sfunc which will take a direction, and add the sine and cosine of that into two accumulators. The final function then converts the two components back into a direction using atan2.
I can’t work out how to define the sfunc so that the current state consists of two components e.g. (float, float). The documentation is a bit short on concrete examples, so any help is appreciated.
You can make use of an ARRAY type internally. Argument type can still be any numeric type. Demonstrating with
float(=double precision):The transition function
f_circavg()is definedSTRICT, so it ignores rows withNULLinput. It also sets a third array element to identify sets with one or more input rows – else theCASEthe final function returnsNULL.Temporary table for testing:
I threw in a
NULLvalue to also test theSTRICTmagic. Call:Cross check:
Returns the same. Seems to work. In test with a bigger table the last expression with regular aggregate functions was 4x faster than the custom aggregate.
Test for zero input rows / only NULL input:
Returns
NULLin both cases.