Skip to content

Feature: Polars integration #60

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions downsample_rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ license = "MIT"
[dependencies]
# TODO: perhaps use polars?
argminmax = { version = "0.6.1", features = ["half"] }
# For some reason we need to explicitely add chrono, otherwise polars refuses to compile?
chrono = "0.4.31"
polars = { version = "0.33.2", features = ["lazy", "streaming", "zip_with"] }
half = { version = "2.3.1", default-features = false , features=["num-traits"], optional = true}
num-traits = { version = "0.2.17", default-features = false }
once_cell = "1"
Expand Down
115 changes: 115 additions & 0 deletions downsample_rs/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use num_traits::AsPrimitive;
use polars::prelude::{ChunkAgg, ChunkAnyValue, ChunkedArray, Float64Type};

use crate::types::Num;

Expand Down Expand Up @@ -31,3 +32,117 @@ where
self.iter().fold(0f64, |acc, &x| acc + x.as_()) as f64 / self.len() as f64
}
}

impl<T> Average for Vec<T>
where
T: Num + AsPrimitive<f64>,
{
fn average(&self) -> f64 {
self.iter().fold(0f64, |acc, &x| acc + x.as_()) as f64 / self.len() as f64
}
}

pub trait LttbParam {
type IterType: Iterator<Item = f64>;
type SliceType: LttbParam;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType;

fn get(&self, index: usize) -> f64;

fn into_iter(&self) -> Self::IterType;

fn len(&self) -> usize;

fn average(&self) -> f64;
}

impl<T> LttbParam for [T]
where
T: Num + AsPrimitive<f64>,
{
type IterType = std::vec::IntoIter<f64>;
type SliceType = std::vec::Vec<f64>;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType {
self[start_idx..end_idx].iter().map(|v| v.as_()).collect()
}

fn get(&self, index: usize) -> f64 {
self[index].as_()
}

fn into_iter(&self) -> Self::IterType {
IntoIterator::into_iter(self.iter().map(|v| v.as_()).collect::<Vec<f64>>())
}

fn len(&self) -> usize {
self.len()
}

fn average(&self) -> f64 {
Average::average(self)
}
}

impl<T> LttbParam for Vec<T>
where
T: Num + AsPrimitive<f64>,
{
type IterType = std::vec::IntoIter<f64>;
type SliceType = std::vec::Vec<f64>;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType {
self[start_idx..end_idx].iter().map(|v| v.as_()).collect()
}

fn get(&self, index: usize) -> f64 {
self[index].as_()
}

fn into_iter(&self) -> Self::IterType {
IntoIterator::into_iter(self.iter().map(|v| v.as_()).collect::<Vec<f64>>())
}

fn len(&self) -> usize {
self.len()
}

fn average(&self) -> f64 {
Average::average(self)
}
}

impl LttbParam for ChunkedArray<Float64Type> {
type IterType = std::vec::IntoIter<f64>;
type SliceType = ChunkedArray<Float64Type>;

fn slice(&self, start_idx: usize, end_idx: usize) -> Self::SliceType {
self.slice(start_idx as i64, end_idx - start_idx)
}

fn get(&self, index: usize) -> f64 {
match self
.get_any_value(index)
.unwrap()
.cast(&polars::prelude::DataType::Float64)
.unwrap()
{
polars::prelude::AnyValue::Float64(x) => x,
_ => unreachable!(), // this can never be reached, as it should have panicked when casting
}
}

fn into_iter(&self) -> Self::IterType {
// TODO: fix this so we don't do any needless copying
self.into_no_null_iter().collect::<Vec<f64>>().into_iter()
}

fn len(&self) -> usize {
self.len()
}

fn average(&self) -> f64 {
self.mean().unwrap_or(0.0)
}
}
Loading