From 2a9fc0306cf5e15a36e6577b2032d01519976ba5 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sat, 31 Aug 2024 21:07:32 +0800 Subject: [PATCH 01/11] implement kurtosis_pop udaf --- .../functions-aggregate/src/kurtosis_pop.rs | 206 ++++++++++++++++++ datafusion/functions-aggregate/src/lib.rs | 2 + 2 files changed, 208 insertions(+) create mode 100644 datafusion/functions-aggregate/src/kurtosis_pop.rs diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs new file mode 100644 index 000000000000..646b64bb7e91 --- /dev/null +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -0,0 +1,206 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use arrow::array::{Array, ArrayRef, Float64Array, UInt64Array}; +use arrow::compute::cast; +use arrow_schema::{DataType, Field}; +use datafusion_common::{ + downcast_value, plan_err, unwrap_or_internal_err, DataFusionError, Result, + ScalarValue, +}; +use datafusion_expr::{Accumulator, AggregateUDFImpl, Signature, Volatility}; +use datafusion_functions_aggregate_common::accumulator::{ + AccumulatorArgs, StateFieldsArgs, +}; +use std::any::Any; +use std::fmt::Debug; + +make_udaf_expr_and_func!( + KurtosisPopFunction, + kurtosis_pop, + x, + "Calculates the excess kurtosis (Fisher’s definition) without bias correction.", + kurtosis_pop_udaf +); + +pub struct KurtosisPopFunction { + signature: Signature, +} + +impl Debug for KurtosisPopFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("KurtosisPopFunction") + .field("signature", &self.signature) + .finish() + } +} + +impl Default for KurtosisPopFunction { + fn default() -> Self { + Self::new() + } +} + +impl KurtosisPopFunction { + pub fn new() -> Self { + Self { + signature: Signature::numeric(1, Volatility::Immutable), + } + } +} + +impl AggregateUDFImpl for KurtosisPopFunction { + fn as_any(&self) -> &dyn Any { + self + } + + fn name(&self) -> &str { + "kurtosis_pop" + } + + fn signature(&self) -> &Signature { + &self.signature + } + + fn return_type(&self, arg_types: &[DataType]) -> Result { + if !arg_types[0].is_numeric() { + return plan_err!("KurtosisPop requires numeric input types"); + } + + Ok(DataType::Float64) + } + + fn state_fields(&self, _args: StateFieldsArgs) -> Result> { + Ok(vec![ + Field::new("count", DataType::UInt64, true), + Field::new("sum", DataType::Float64, true), + Field::new("sum_sqr", DataType::Float64, true), + Field::new("sum_cub", DataType::Float64, true), + Field::new("sum_four", DataType::Float64, true), + ]) + } + + fn accumulator(&self, _acc_args: AccumulatorArgs) -> Result> { + Ok(Box::new(KurtosisPopAccumulator::new())) + } +} + +#[derive(Debug, Default)] +pub struct KurtosisPopAccumulator { + count: u64, + sum: f64, + sum_sqr: f64, + sum_cub: f64, + sum_four: f64, +} + +impl KurtosisPopAccumulator { + pub fn new() -> Self { + Self { + count: 0, + sum: 0.0, + sum_sqr: 0.0, + sum_cub: 0.0, + sum_four: 0.0, + } + } +} + +impl Accumulator for KurtosisPopAccumulator { + fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> { + let values = &cast(&values[0], &DataType::Float64)?; + let mut arr = downcast_value!(values, Float64Array).iter().flatten(); + for i in 0..values.len() { + let value = if values.is_valid(i) { arr.next() } else { None }; + + if value.is_none() { + continue; + } + + let value = unwrap_or_internal_err!(value); + self.count += 1; + self.sum += value; + self.sum_sqr += value * value; + self.sum_cub += value * value * value; + self.sum_four += value * value * value * value; + } + Ok(()) + } + + fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> { + let counts = downcast_value!(states[0], UInt64Array); + let sums = downcast_value!(states[1], Float64Array); + let sum_sqrs = downcast_value!(states[2], Float64Array); + let sum_cubs = downcast_value!(states[3], Float64Array); + let sum_fours = downcast_value!(states[4], Float64Array); + + for i in 0..counts.len() { + let c = counts.value(i); + if c == 0 { + continue; + } + self.count += c; + self.sum += sums.value(i); + self.sum_sqr += sum_sqrs.value(i); + self.sum_cub += sum_cubs.value(i); + self.sum_four += sum_fours.value(i); + } + + Ok(()) + } + + fn evaluate(&mut self) -> Result { + if self.count < 1 { + return Ok(ScalarValue::Float64(None)); + } + + let count_64 = 1_f64 / self.count as f64; + let m4 = count_64 + * (self.sum_four - 4.0 * self.sum_cub * self.sum * count_64 + + 6.0 * self.sum_sqr * self.sum * self.sum * count_64 * count_64 + - 3.0 + * self.sum + * self.sum + * self.sum + * self.sum + * count_64 + * count_64 + * count_64); + + let m2 = (self.sum_sqr - self.sum * self.sum * count_64) * count_64; + if m2 <= 0.0 { + return Ok(ScalarValue::Float64(None)); + } + + let target = m4 / (m2 * m2) - 3.0; + Ok(ScalarValue::Float64(Some(target))) + } + + fn size(&self) -> usize { + size_of_val(self) + } + + fn state(&mut self) -> Result> { + Ok(vec![ + ScalarValue::from(self.count), + ScalarValue::from(self.sum), + ScalarValue::from(self.sum_sqr), + ScalarValue::from(self.sum_cub), + ScalarValue::from(self.sum_four), + ]) + } +} diff --git a/datafusion/functions-aggregate/src/lib.rs b/datafusion/functions-aggregate/src/lib.rs index b54cd181a0cb..479d08cf94ea 100644 --- a/datafusion/functions-aggregate/src/lib.rs +++ b/datafusion/functions-aggregate/src/lib.rs @@ -78,6 +78,7 @@ pub mod average; pub mod bit_and_or_xor; pub mod bool_and_or; pub mod grouping; +pub mod kurtosis_pop; pub mod nth_value; pub mod string_agg; @@ -169,6 +170,7 @@ pub fn all_default_aggregate_functions() -> Vec> { average::avg_udaf(), grouping::grouping_udaf(), nth_value::nth_value_udaf(), + kurtosis_pop::kurtosis_pop_udaf(), ] } From 13b00c581b713c3e653b4344ac2a87f6a8f67d40 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sat, 31 Aug 2024 21:08:00 +0800 Subject: [PATCH 02/11] add tests --- .../tests/cases/roundtrip_logical_plan.rs | 2 + .../sqllogictest/test_files/aggregate.slt | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs index e174d1b50713..5643749dd607 100644 --- a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs +++ b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs @@ -72,6 +72,7 @@ use datafusion_functions_aggregate::average::avg_udaf; use datafusion_functions_aggregate::expr_fn::{ approx_distinct, array_agg, avg, bit_and, bit_or, bit_xor, bool_and, bool_or, corr, }; +use datafusion_functions_aggregate::kurtosis_pop::kurtosis_pop; use datafusion_functions_aggregate::string_agg::string_agg; use datafusion_proto::bytes::{ logical_plan_from_bytes, logical_plan_from_bytes_with_extension_codec, @@ -903,6 +904,7 @@ async fn roundtrip_expr_api() -> Result<()> { vec![lit(10), lit(20), lit(30)], ), row_number(), + kurtosis_pop(lit(1)), ]; // ensure expressions created with the expr api can be round tripped diff --git a/datafusion/sqllogictest/test_files/aggregate.slt b/datafusion/sqllogictest/test_files/aggregate.slt index 45cb4d4615d7..d9f93cfe9f23 100644 --- a/datafusion/sqllogictest/test_files/aggregate.slt +++ b/datafusion/sqllogictest/test_files/aggregate.slt @@ -5863,3 +5863,47 @@ ORDER BY k; ---- 1 1.8125 6.8007813 Float16 Float16 2 8.5 8.5 Float16 Float16 + +# The result is 0.19432323191699075 actually +query R +SELECT kurtosis_pop(col) FROM VALUES (1), (10), (100), (10), (1) as tab(col); +---- +0.194323231917 + +# The result is -1.153061224489787 actually +query R +SELECT kurtosis_pop(col) FROM VALUES (1), (2), (3), (2), (1) as tab(col); +---- +-1.15306122449 + +query R +SELECT kurtosis_pop(col) FROM VALUES (1.0), (10.0), (100.0), (10.0), (1.0) as tab(col); +---- +0.194323231917 + +query error DataFusion error: Error during planning: KurtosisPop requires numeric input types +SELECT kurtosis_pop(col) FROM VALUES ('1'), ('10'), ('100'), ('10'), ('1') as tab(col); + +query R +SELECT kurtosis_pop(col) FROM VALUES (1.0) as tab(col); +---- +NULL + +statement ok +CREATE TABLE t1(c1 int); + +query R +SELECT kurtosis_pop(c1) FROM t1; +---- +NULL + +statement ok +INSERT INTO t1 VALUES (1), (10), (100), (10), (1); + +query R +SELECT kurtosis_pop(c1) FROM t1; +---- +0.194323231917 + +statement ok +DROP TABLE t1; \ No newline at end of file From 49d2dc6d8978444e5d1ae479769ad6e371f22762 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sat, 31 Aug 2024 22:19:45 +0800 Subject: [PATCH 03/11] add empty end line --- datafusion/sqllogictest/test_files/aggregate.slt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/sqllogictest/test_files/aggregate.slt b/datafusion/sqllogictest/test_files/aggregate.slt index d9f93cfe9f23..418e10cb7dbd 100644 --- a/datafusion/sqllogictest/test_files/aggregate.slt +++ b/datafusion/sqllogictest/test_files/aggregate.slt @@ -5906,4 +5906,4 @@ SELECT kurtosis_pop(c1) FROM t1; 0.194323231917 statement ok -DROP TABLE t1; \ No newline at end of file +DROP TABLE t1; From 901d38b2fd25e4637bb41d83e95272b93be4d587 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sat, 31 Aug 2024 22:25:01 +0800 Subject: [PATCH 04/11] fix MSRV check --- datafusion/functions-aggregate/src/kurtosis_pop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs index 646b64bb7e91..53cf24ad579b 100644 --- a/datafusion/functions-aggregate/src/kurtosis_pop.rs +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -191,7 +191,7 @@ impl Accumulator for KurtosisPopAccumulator { } fn size(&self) -> usize { - size_of_val(self) + std::mem::size_of_val(self) } fn state(&mut self) -> Result> { From 2a493312612d58ed62f0e664558c8d357b71298f Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sat, 31 Aug 2024 22:45:38 +0800 Subject: [PATCH 05/11] fix the null input and enhance tests --- .../functions-aggregate/src/kurtosis_pop.rs | 2 +- datafusion/sqllogictest/test_files/aggregate.slt | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs index 53cf24ad579b..b50a96774191 100644 --- a/datafusion/functions-aggregate/src/kurtosis_pop.rs +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -77,7 +77,7 @@ impl AggregateUDFImpl for KurtosisPopFunction { } fn return_type(&self, arg_types: &[DataType]) -> Result { - if !arg_types[0].is_numeric() { + if !arg_types[0].is_null() && !arg_types[0].is_numeric() { return plan_err!("KurtosisPop requires numeric input types"); } diff --git a/datafusion/sqllogictest/test_files/aggregate.slt b/datafusion/sqllogictest/test_files/aggregate.slt index 418e10cb7dbd..7acd12b85487 100644 --- a/datafusion/sqllogictest/test_files/aggregate.slt +++ b/datafusion/sqllogictest/test_files/aggregate.slt @@ -5889,6 +5889,21 @@ SELECT kurtosis_pop(col) FROM VALUES (1.0) as tab(col); ---- NULL +query R +SELECT kurtosis_pop(1) +---- +NULL + +query R +SELECT kurtosis_pop(1.0) +---- +NULL + +query R +SELECT kurtosis_pop(null) +---- +NULL + statement ok CREATE TABLE t1(c1 int); From 31e48c9ab6e2960240b5ad0a0093df8640849c9d Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sat, 31 Aug 2024 22:57:22 +0800 Subject: [PATCH 06/11] refactor the aggregation --- .../functions-aggregate/src/kurtosis_pop.rs | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs index b50a96774191..12d5671e24ae 100644 --- a/datafusion/functions-aggregate/src/kurtosis_pop.rs +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -134,9 +134,9 @@ impl Accumulator for KurtosisPopAccumulator { let value = unwrap_or_internal_err!(value); self.count += 1; self.sum += value; - self.sum_sqr += value * value; - self.sum_cub += value * value * value; - self.sum_four += value * value * value * value; + self.sum_sqr += value.powi(2); + self.sum_cub += value.powi(3); + self.sum_four += value.powi(4); } Ok(()) } @@ -171,22 +171,15 @@ impl Accumulator for KurtosisPopAccumulator { let count_64 = 1_f64 / self.count as f64; let m4 = count_64 * (self.sum_four - 4.0 * self.sum_cub * self.sum * count_64 - + 6.0 * self.sum_sqr * self.sum * self.sum * count_64 * count_64 - - 3.0 - * self.sum - * self.sum - * self.sum - * self.sum - * count_64 - * count_64 - * count_64); - - let m2 = (self.sum_sqr - self.sum * self.sum * count_64) * count_64; + + 6.0 * self.sum_sqr * self.sum.powi(2) * count_64.powi(2) + - 3.0 * self.sum.powi(4) * count_64.powi(3)); + + let m2 = (self.sum_sqr - self.sum.powi(2) * count_64) * count_64; if m2 <= 0.0 { return Ok(ScalarValue::Float64(None)); } - let target = m4 / (m2 * m2) - 3.0; + let target = m4 / (m2.powi(2)) - 3.0; Ok(ScalarValue::Float64(Some(target))) } From 709cc0f40b760e07e6dfd3f530f1f1512047cfab Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sun, 1 Sep 2024 23:12:15 +0800 Subject: [PATCH 07/11] address the review comments --- .../functions-aggregate/src/kurtosis_pop.rs | 26 ++++++------------- .../sqllogictest/test_files/aggregate.slt | 4 ++- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs index 12d5671e24ae..ffde289919d7 100644 --- a/datafusion/functions-aggregate/src/kurtosis_pop.rs +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -18,10 +18,8 @@ use arrow::array::{Array, ArrayRef, Float64Array, UInt64Array}; use arrow::compute::cast; use arrow_schema::{DataType, Field}; -use datafusion_common::{ - downcast_value, plan_err, unwrap_or_internal_err, DataFusionError, Result, - ScalarValue, -}; +use datafusion_common::cast::as_float64_array; +use datafusion_common::{downcast_value, DataFusionError, Result, ScalarValue}; use datafusion_expr::{Accumulator, AggregateUDFImpl, Signature, Volatility}; use datafusion_functions_aggregate_common::accumulator::{ AccumulatorArgs, StateFieldsArgs, @@ -76,11 +74,7 @@ impl AggregateUDFImpl for KurtosisPopFunction { &self.signature } - fn return_type(&self, arg_types: &[DataType]) -> Result { - if !arg_types[0].is_null() && !arg_types[0].is_numeric() { - return plan_err!("KurtosisPop requires numeric input types"); - } - + fn return_type(&self, _arg_types: &[DataType]) -> Result { Ok(DataType::Float64) } @@ -99,6 +93,9 @@ impl AggregateUDFImpl for KurtosisPopFunction { } } +/// Accumulator for calculating the excess kurtosis (Fisher’s definition) without bias correction. +/// This implementation follows the DuckDB implementation: +/// https://github.com/duckdb/duckdb/blob/main/src/core_functions/aggregate/distributive/kurtosis.cpp #[derive(Debug, Default)] pub struct KurtosisPopAccumulator { count: u64, @@ -123,15 +120,8 @@ impl KurtosisPopAccumulator { impl Accumulator for KurtosisPopAccumulator { fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> { let values = &cast(&values[0], &DataType::Float64)?; - let mut arr = downcast_value!(values, Float64Array).iter().flatten(); - for i in 0..values.len() { - let value = if values.is_valid(i) { arr.next() } else { None }; - - if value.is_none() { - continue; - } - - let value = unwrap_or_internal_err!(value); + let array = as_float64_array(&values)?; + for value in array.iter().flatten() { self.count += 1; self.sum += value; self.sum_sqr += value.powi(2); diff --git a/datafusion/sqllogictest/test_files/aggregate.slt b/datafusion/sqllogictest/test_files/aggregate.slt index 7acd12b85487..c52445c561ee 100644 --- a/datafusion/sqllogictest/test_files/aggregate.slt +++ b/datafusion/sqllogictest/test_files/aggregate.slt @@ -5881,8 +5881,10 @@ SELECT kurtosis_pop(col) FROM VALUES (1.0), (10.0), (100.0), (10.0), (1.0) as ta ---- 0.194323231917 -query error DataFusion error: Error during planning: KurtosisPop requires numeric input types +query R SELECT kurtosis_pop(col) FROM VALUES ('1'), ('10'), ('100'), ('10'), ('1') as tab(col); +---- +0.194323231917 query R SELECT kurtosis_pop(col) FROM VALUES (1.0) as tab(col); From dffe8380aa7bcf330de6bcb5f2484ad42a467f15 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Sun, 1 Sep 2024 23:19:41 +0800 Subject: [PATCH 08/11] add the doc for kurtois_pop --- docs/source/user-guide/sql/aggregate_functions.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/source/user-guide/sql/aggregate_functions.md b/docs/source/user-guide/sql/aggregate_functions.md index edb0e1d0c9f0..1c214084b3fa 100644 --- a/docs/source/user-guide/sql/aggregate_functions.md +++ b/docs/source/user-guide/sql/aggregate_functions.md @@ -252,6 +252,7 @@ last_value(expression [ORDER BY expression]) - [regr_sxx](#regr_sxx) - [regr_syy](#regr_syy) - [regr_sxy](#regr_sxy) +- [kurtosis_pop](#kurtosis_pop) ### `corr` @@ -527,6 +528,19 @@ regr_sxy(expression_y, expression_x) - **expression_x**: Independent variable. Can be a constant, column, or function, and any combination of arithmetic operators. +### `kurtosis_pop` + +Computes the excess kurtosis (Fisher’s definition) without bias correction. + +``` +kurtois_pop(expression) +``` + +#### Arguments + +- **expression**: Expression to operate on. + Can be a constant, column, or function, and any combination of arithmetic operators. + ## Approximate - [approx_distinct](#approx_distinct) From d51d16eca437b204501eb9150037ae5be2674c54 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Mon, 2 Sep 2024 00:06:05 +0800 Subject: [PATCH 09/11] fix the doc style --- datafusion/functions-aggregate/src/kurtosis_pop.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs index ffde289919d7..a9648e463aa9 100644 --- a/datafusion/functions-aggregate/src/kurtosis_pop.rs +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -94,8 +94,8 @@ impl AggregateUDFImpl for KurtosisPopFunction { } /// Accumulator for calculating the excess kurtosis (Fisher’s definition) without bias correction. -/// This implementation follows the DuckDB implementation: -/// https://github.com/duckdb/duckdb/blob/main/src/core_functions/aggregate/distributive/kurtosis.cpp +/// This implementation follows the [DuckDB implementation]: +/// #[derive(Debug, Default)] pub struct KurtosisPopAccumulator { count: u64, From 4f06d04f6d05649dd8841fd9636c195635c27974 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Tue, 3 Sep 2024 20:55:14 +0800 Subject: [PATCH 10/11] use coercible signature --- datafusion/functions-aggregate/src/kurtosis_pop.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs index a9648e463aa9..4a95ed64997a 100644 --- a/datafusion/functions-aggregate/src/kurtosis_pop.rs +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -56,7 +56,10 @@ impl Default for KurtosisPopFunction { impl KurtosisPopFunction { pub fn new() -> Self { Self { - signature: Signature::numeric(1, Volatility::Immutable), + signature: Signature::coercible( + vec![DataType::Float64], + Volatility::Immutable, + ), } } } From b56de3fa535df0efa7ea954465540151902c0353 Mon Sep 17 00:00:00 2001 From: Jia-Xuan Liu Date: Wed, 4 Sep 2024 12:55:25 +0800 Subject: [PATCH 11/11] remove unused cast --- datafusion/functions-aggregate/src/kurtosis_pop.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/datafusion/functions-aggregate/src/kurtosis_pop.rs b/datafusion/functions-aggregate/src/kurtosis_pop.rs index 4a95ed64997a..ac173a0ee579 100644 --- a/datafusion/functions-aggregate/src/kurtosis_pop.rs +++ b/datafusion/functions-aggregate/src/kurtosis_pop.rs @@ -16,7 +16,6 @@ // under the License. use arrow::array::{Array, ArrayRef, Float64Array, UInt64Array}; -use arrow::compute::cast; use arrow_schema::{DataType, Field}; use datafusion_common::cast::as_float64_array; use datafusion_common::{downcast_value, DataFusionError, Result, ScalarValue}; @@ -122,8 +121,7 @@ impl KurtosisPopAccumulator { impl Accumulator for KurtosisPopAccumulator { fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> { - let values = &cast(&values[0], &DataType::Float64)?; - let array = as_float64_array(&values)?; + let array = as_float64_array(&values[0])?; for value in array.iter().flatten() { self.count += 1; self.sum += value;