diff --git a/crates/polars-core/src/series/any_value.rs b/crates/polars-core/src/series/any_value.rs index d34bad6512df..aa4cc7bf1e5b 100644 --- a/crates/polars-core/src/series/any_value.rs +++ b/crates/polars-core/src/series/any_value.rs @@ -3,12 +3,6 @@ use std::fmt::Write; use crate::prelude::*; use crate::utils::get_supertype; -fn any_values_to_primitive(avs: &[AnyValue]) -> ChunkedArray { - avs.iter() - .map(|av| av.extract::()) - .collect_trusted() -} - #[cfg(feature = "dtype-decimal")] fn any_values_to_decimal( avs: &[AnyValue], @@ -225,36 +219,36 @@ impl Series { ) -> PolarsResult { let mut s = match dtype { #[cfg(feature = "dtype-i8")] - DataType::Int8 => any_values_to_primitive::(av).into_series(), + DataType::Int8 => any_values_to_integer::(av, strict)?.into_series(), #[cfg(feature = "dtype-i16")] - DataType::Int16 => any_values_to_primitive::(av).into_series(), - DataType::Int32 => any_values_to_primitive::(av).into_series(), - DataType::Int64 => any_values_to_primitive::(av).into_series(), + DataType::Int16 => any_values_to_integer::(av, strict)?.into_series(), + DataType::Int32 => any_values_to_integer::(av, strict)?.into_series(), + DataType::Int64 => any_values_to_integer::(av, strict)?.into_series(), #[cfg(feature = "dtype-u8")] - DataType::UInt8 => any_values_to_primitive::(av).into_series(), + DataType::UInt8 => any_values_to_integer::(av, strict)?.into_series(), #[cfg(feature = "dtype-u16")] - DataType::UInt16 => any_values_to_primitive::(av).into_series(), - DataType::UInt32 => any_values_to_primitive::(av).into_series(), - DataType::UInt64 => any_values_to_primitive::(av).into_series(), - DataType::Float32 => any_values_to_primitive::(av).into_series(), - DataType::Float64 => any_values_to_primitive::(av).into_series(), + DataType::UInt16 => any_values_to_integer::(av, strict)?.into_series(), + DataType::UInt32 => any_values_to_integer::(av, strict)?.into_series(), + DataType::UInt64 => any_values_to_integer::(av, strict)?.into_series(), + DataType::Float32 => any_values_to_f32(av, strict)?.into_series(), + DataType::Float64 => any_values_to_f64(av, strict)?.into_series(), DataType::String => any_values_to_string(av, strict)?.into_series(), DataType::Binary => any_values_to_binary(av, strict)?.into_series(), DataType::Boolean => any_values_to_bool(av, strict)?.into_series(), #[cfg(feature = "dtype-date")] - DataType::Date => any_values_to_primitive::(av) + DataType::Date => any_values_to_primitive_nonstrict::(av) .into_date() .into_series(), #[cfg(feature = "dtype-datetime")] - DataType::Datetime(tu, tz) => any_values_to_primitive::(av) + DataType::Datetime(tu, tz) => any_values_to_primitive_nonstrict::(av) .into_datetime(*tu, (*tz).clone()) .into_series(), #[cfg(feature = "dtype-time")] - DataType::Time => any_values_to_primitive::(av) + DataType::Time => any_values_to_primitive_nonstrict::(av) .into_time() .into_series(), #[cfg(feature = "dtype-duration")] - DataType::Duration(tu) => any_values_to_primitive::(av) + DataType::Duration(tu) => any_values_to_primitive_nonstrict::(av) .into_duration(*tu) .into_series(), #[cfg(feature = "dtype-decimal")] @@ -460,6 +454,82 @@ impl Series { } } +fn any_values_to_primitive_nonstrict(values: &[AnyValue]) -> ChunkedArray { + values + .iter() + .map(|av| av.extract::()) + .collect_trusted() +} + +fn any_values_to_integer( + values: &[AnyValue], + strict: bool, +) -> PolarsResult> { + fn any_values_to_integer_strict( + values: &[AnyValue], + ) -> PolarsResult> { + let mut builder = PrimitiveChunkedBuilder::::new("", values.len()); + for av in values { + match av { + av if av.is_integer() => { + let opt_val = av.extract::(); + let val = match opt_val { + Some(v) => v, + None => return Err(invalid_value_error(&T::get_dtype(), av)), + }; + builder.append_value(val) + }, + AnyValue::Null => builder.append_null(), + av => return Err(invalid_value_error(&T::get_dtype(), av)), + } + } + Ok(builder.finish()) + } + if strict { + any_values_to_integer_strict::(values) + } else { + Ok(any_values_to_primitive_nonstrict::(values)) + } +} + +fn any_values_to_f32(values: &[AnyValue], strict: bool) -> PolarsResult { + fn any_values_to_f32_strict(values: &[AnyValue]) -> PolarsResult { + let mut builder = PrimitiveChunkedBuilder::::new("", values.len()); + for av in values { + match av { + AnyValue::Float32(i) => builder.append_value(*i), + AnyValue::Null => builder.append_null(), + av => return Err(invalid_value_error(&DataType::Float32, av)), + } + } + Ok(builder.finish()) + } + if strict { + any_values_to_f32_strict(values) + } else { + Ok(any_values_to_primitive_nonstrict::(values)) + } +} +fn any_values_to_f64(values: &[AnyValue], strict: bool) -> PolarsResult { + fn any_values_to_f64_strict(values: &[AnyValue]) -> PolarsResult { + let mut builder = PrimitiveChunkedBuilder::::new("", values.len()); + for av in values { + match av { + AnyValue::Float64(i) => builder.append_value(*i), + AnyValue::Float32(i) => builder.append_value(*i as f64), + AnyValue::Null => builder.append_null(), + av => return Err(invalid_value_error(&DataType::Float64, av)), + } + } + Ok(builder.finish()) + } + if strict { + any_values_to_f64_strict(values) + } else { + Ok(any_values_to_primitive_nonstrict::(values)) + } +} + fn any_values_to_bool(values: &[AnyValue], strict: bool) -> PolarsResult { if strict { any_values_to_bool_strict(values)