Skip to content

Commit

Permalink
Struct error on different dict orders (#3447)
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchie46 committed May 20, 2022
1 parent b085356 commit 3484245
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 14 deletions.
34 changes: 22 additions & 12 deletions polars/polars-core/src/series/any_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ fn any_values_to_list(avs: &[AnyValue]) -> ListChunked {
impl<'a, T: AsRef<[AnyValue<'a>]>> NamedFrom<T, [AnyValue<'a>]> for Series {
fn new(name: &str, v: T) -> Self {
let av = v.as_ref();
Series::from_any_values(name, av)
Series::from_any_values(name, av).unwrap()
}
}

impl Series {
fn from_any_values<'a>(name: &str, av: &[AnyValue<'a>]) -> Series {
pub fn from_any_values<'a>(name: &str, av: &[AnyValue<'a>]) -> Result<Series> {
match av.iter().find(|av| !matches!(av, AnyValue::Null)) {
None => Series::full_null(name, av.len(), &DataType::Int32),
None => Ok(Series::full_null(name, av.len(), &DataType::Int32)),
Some(av_) => {
let mut s = match av_ {
AnyValue::Int32(_) => any_values_to_primitive::<Int32Type>(av).into_series(),
Expand Down Expand Up @@ -88,23 +88,33 @@ impl Series {
for (i, field) in fields.iter().enumerate() {
let mut field_avs = Vec::with_capacity(av.len());

av.iter().for_each(|av| match av {
AnyValue::StructOwned(pl) => {
let av_val = pl.0[i].clone();
field_avs.push(av_val)
for av in av.iter() {
match av {
AnyValue::StructOwned(pl) => {
for (l, r) in fields.iter().zip(pl.1.iter()) {
if l != r {
return Err(PolarsError::ComputeError(
"structs orders must remain the same".into(),
));
}
}

let av_val = pl.0[i].clone();
field_avs.push(av_val)
}
_ => field_avs.push(AnyValue::Null),
}
_ => field_avs.push(AnyValue::Null),
});
}
series_fields.push(Series::new(field.name(), &field_avs))
}
return StructChunked::new(name, &series_fields)
return Ok(StructChunked::new(name, &series_fields)
.unwrap()
.into_series();
.into_series());
}
av => panic!("av {:?} not implemented", av),
};
s.rename(name);
s
Ok(s)
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions py-polars/src/series.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,11 @@ impl From<Series> for PySeries {
)]
impl PySeries {
#[staticmethod]
pub fn new_from_anyvalues(name: &str, val: Vec<Wrap<AnyValue<'_>>>) -> PySeries {
pub fn new_from_anyvalues(name: &str, val: Vec<Wrap<AnyValue<'_>>>) -> PyResult<PySeries> {
let avs = slice_extract_wrapped(&val);
Series::new(name, avs).into()
// from anyvalues is fallible
let s = Series::from_any_values(name, avs).map_err(PyPolarsErr::from)?;
Ok(s.into())
}

#[staticmethod]
Expand Down
10 changes: 10 additions & 0 deletions py-polars/tests/test_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pandas as pd
import pyarrow as pa
import pytest

import polars as pl
from polars.internals.frame import DataFrame
Expand Down Expand Up @@ -406,3 +407,12 @@ def test_struct_comparison() -> None:
"col1": [{"a": 3, "b": 4}],
"col2": [{"a": 3, "b": 4}],
}


def test_struct_order() -> None:
with pytest.raises(pl.ComputeError, match="structs orders must remain the same"):
pl.DataFrame(
{
"col1": [{"a": 1, "b": 2}, {"b": 4, "a": 3}],
}
)

0 comments on commit 3484245

Please sign in to comment.