Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/catalog/default/default_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ static DefaultMacro internal_macros[] = {
{DEFAULT_SCHEMA, "list_first", {"l", nullptr}, "list_aggr(l, 'first')"},
{DEFAULT_SCHEMA, "list_any_value", {"l", nullptr}, "list_aggr(l, 'any_value')"},
{DEFAULT_SCHEMA, "list_kurtosis", {"l", nullptr}, "list_aggr(l, 'kurtosis')"},
{DEFAULT_SCHEMA, "list_kurtosis_pop", {"l", nullptr}, "list_aggr(l, 'kurtosis_pop')"},
{DEFAULT_SCHEMA, "list_min", {"l", nullptr}, "list_aggr(l, 'min')"},
{DEFAULT_SCHEMA, "list_max", {"l", nullptr}, "list_aggr(l, 'max')"},
{DEFAULT_SCHEMA, "list_product", {"l", nullptr}, "list_aggr(l, 'product')"},
Expand Down
7 changes: 7 additions & 0 deletions src/core_functions/aggregate/distributive/functions.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@
"example": "",
"type": "aggregate_function"
},
{
"name": "kurtosis_pop",
"parameters": "x",
"description": "Returns the excess kurtosis (Fisher’s definition) of all input values, without bias correction",
"example": "",
"type": "aggregate_function"
},
{
"name": "min",
"parameters": "arg",
Expand Down
30 changes: 25 additions & 5 deletions src/core_functions/aggregate/distributive/kurtosis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ struct KurtosisState {
double sum_four;
};

struct KurtosisFlagBiasCorrection {};

struct KurtosisFlagNoBiasCorrection {};

template <class KURTOSIS_FLAG>
struct KurtosisOperation {
template <class STATE>
static void Initialize(STATE &state) {
Expand Down Expand Up @@ -53,7 +58,11 @@ struct KurtosisOperation {
template <class TARGET_TYPE, class STATE>
static void Finalize(STATE &state, TARGET_TYPE &target, AggregateFinalizeData &finalize_data) {
auto n = (double)state.n;
if (n <= 3) {
if (n <= 1) {
finalize_data.ReturnNull();
return;
}
if (std::is_same<KURTOSIS_FLAG, KurtosisFlagBiasCorrection>::value && n <= 3) {
finalize_data.ReturnNull();
return;
}
Expand All @@ -70,11 +79,15 @@ struct KurtosisOperation {
6 * state.sum_sqr * state.sum * state.sum * temp * temp - 3 * pow(state.sum, 4) * pow(temp, 3));

double m2 = temp * (state.sum_sqr - state.sum * state.sum * temp);
if (m2 <= 0 || ((n - 2) * (n - 3)) == 0) { // m2 shouldn't be below 0 but floating points are weird
if (m2 <= 0) { // m2 shouldn't be below 0 but floating points are weird
finalize_data.ReturnNull();
return;
}
target = (n - 1) * ((n + 1) * m4 / (m2 * m2) - 3 * (n - 1)) / ((n - 2) * (n - 3));
if (std::is_same<KURTOSIS_FLAG, KurtosisFlagNoBiasCorrection>::value) {
target = m4 / (m2 * m2) - 3;
} else {
target = (n - 1) * ((n + 1) * m4 / (m2 * m2) - 3 * (n - 1)) / ((n - 2) * (n - 3));
}
if (!Value::DoubleIsFinite(target)) {
throw OutOfRangeException("Kurtosis is out of range!");
}
Expand All @@ -86,8 +99,15 @@ struct KurtosisOperation {
};

AggregateFunction KurtosisFun::GetFunction() {
return AggregateFunction::UnaryAggregate<KurtosisState, double, double, KurtosisOperation>(LogicalType::DOUBLE,
LogicalType::DOUBLE);
return AggregateFunction::UnaryAggregate<KurtosisState, double, double,
KurtosisOperation<KurtosisFlagBiasCorrection>>(LogicalType::DOUBLE,
LogicalType::DOUBLE);
}

AggregateFunction KurtosisPopFun::GetFunction() {
return AggregateFunction::UnaryAggregate<KurtosisState, double, double,
KurtosisOperation<KurtosisFlagNoBiasCorrection>>(LogicalType::DOUBLE,
LogicalType::DOUBLE);
}

} // namespace duckdb
1 change: 1 addition & 0 deletions src/core_functions/function_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ static StaticFunctionDefinition internal_functions[] = {
DUCKDB_SCALAR_FUNCTION_SET(JulianDayFun),
DUCKDB_AGGREGATE_FUNCTION(KahanSumFun),
DUCKDB_AGGREGATE_FUNCTION(KurtosisFun),
DUCKDB_AGGREGATE_FUNCTION(KurtosisPopFun),
DUCKDB_SCALAR_FUNCTION_SET(LastDayFun),
DUCKDB_SCALAR_FUNCTION_SET_ALIAS(LcmFun),
DUCKDB_SCALAR_FUNCTION_SET(LeastFun),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ struct KurtosisFun {
static AggregateFunction GetFunction();
};

struct KurtosisPopFun {
static constexpr const char *Name = "kurtosis_pop";
static constexpr const char *Parameters = "x";
static constexpr const char *Description = "Returns the excess kurtosis (Fisher’s definition) of all input values, without bias correction";
static constexpr const char *Example = "";

static AggregateFunction GetFunction();
};

struct MinFun {
static constexpr const char *Name = "min";
static constexpr const char *Parameters = "arg";
Expand Down
10 changes: 10 additions & 0 deletions test/sql/aggregate/aggregates/test_kurtosis.test
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ select kurtosis(k), kurtosis(v), kurtosis(v2) from aggr;
----
11.000000 -1.961428 -1.445120

query III
select kurtosis_pop(k), kurtosis_pop(v), kurtosis_pop(v2) from aggr;
----
6.100000 -1.676857 -1.358688

query I
with onetwo as (select range::float as v from range(1,3)) select kurtosis_pop(v) from onetwo;
----
-2.0

query I
select kurtosis(v2) from aggr group by v ORDER BY ALL;
----
Expand Down
10 changes: 10 additions & 0 deletions test/sql/function/list/aggregates/kurtosis.test
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ NULL
NULL
NULL

query I
select list_kurtosis_pop(k) from aggr;
----
6.100000
-1.676857
-1.358688
NULL
NULL
NULL

# incorrect usage
statement error
select list_kurtosis()