There were a few problems that @jqurious pointed out and would like to provide a solution.
For example, the literal error is caused by having lit(1.0) in front of + self.gmean()
fn gmean_annualized_expr(self, freq:Option<&str>) -> Expr {
let annualize_factor = lit(annualize_scaler(freq).unwrap());
( lit(1.0) + self.gmean()).pow(annualize_factor) - lit(1.0)
}
By moving lit(1.0) after self.gmean() fixed the problem.
fn gmean_annualized_expr(self, freq:Option<&str>) -> Expr {
let annualize_factor = lit(annualize_scaler(freq).unwrap());
(self.gmean() + lit(1.0)).pow(annualize_factor) - lit(1.0)
}
Here is the full expression for reference
fn geometric_mean(values: &Float64Chunked) -> f64 {
let adjusted_values: Float64Chunked = values.apply(|opt_v| opt_v.map(|x| x + 1.0));
let product: f64 = adjusted_values
.into_iter()
.filter_map(|opt| opt) // Remove None values
.product(); // Compute the product of present values
let count = adjusted_values.len() as f64;
product.powf(1.0 / count)
}
fn gmean(series: &[Series]) -> PolarsResult<Series> {
let _series = &series[0]; // This is getting the actual values from the series since there are multiple types of data returns from a series
let _chunk_array = _series.f64()?;
let geo_mean= geometric_mean(_chunk_array) - 1.0;
let new_chunk = Float64Chunked::from_vec(_series.name().clone(), vec![geo_mean]);
Ok(new_chunk.into_series())
}
fn gmean_column(series: &Column) -> Result<Option<Column>,PolarsError> {
let materialized_series_slice = std::slice::from_ref(series.as_materialized_series());
Ok(Some(gmean(materialized_series_slice)?.into_column()))
}
pub trait GeoMean {
fn gmean(self) -> Expr;
}
impl GeoMean for Expr {
fn gmean(self) -> Expr {
self.apply(|column| gmean_column(&column),GetOutput::from_type(DataType::Float64))
}
}