Skip to content

Commit 0615d6b

Browse files
Implement fill_missing for all integer dtypes (#1078)
* Add cases for all int types * Return error instead of panicking; test * Clarify reason for panic in match * Remove unrelate file Whoops! * Test all integer types
1 parent eff2d5f commit 0615d6b

2 files changed

Lines changed: 57 additions & 5 deletions

File tree

native/explorer/src/series.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,9 +508,51 @@ pub fn s_fill_missing_with_atom(series: ExSeries, atom: &str) -> Result<ExSeries
508508
}
509509

510510
#[rustler::nif(schedule = "DirtyCpu")]
511-
pub fn s_fill_missing_with_int(series: ExSeries, integer: i64) -> Result<ExSeries, ExplorerError> {
512-
let s = series.i64()?.fill_null_with_values(integer)?.into_series();
513-
Ok(ExSeries::new(s))
511+
pub fn s_fill_missing_with_int(
512+
ex_series: ExSeries,
513+
integer: i64,
514+
) -> Result<ExSeries, ExplorerError> {
515+
let filled_series = match ex_series.dtype() {
516+
DataType::Int8 => ex_series
517+
.i8()?
518+
.fill_null_with_values(integer.try_into()?)?
519+
.into_series(),
520+
DataType::Int16 => ex_series
521+
.i16()?
522+
.fill_null_with_values(integer.try_into()?)?
523+
.into_series(),
524+
DataType::Int32 => ex_series
525+
.i32()?
526+
.fill_null_with_values(integer.try_into()?)?
527+
.into_series(),
528+
DataType::Int64 => ex_series
529+
.i64()?
530+
.fill_null_with_values(integer)?
531+
.into_series(),
532+
DataType::UInt8 => ex_series
533+
.u8()?
534+
.fill_null_with_values(integer.try_into()?)?
535+
.into_series(),
536+
DataType::UInt16 => ex_series
537+
.u16()?
538+
.fill_null_with_values(integer.try_into()?)?
539+
.into_series(),
540+
DataType::UInt32 => ex_series
541+
.u32()?
542+
.fill_null_with_values(integer.try_into()?)?
543+
.into_series(),
544+
DataType::UInt64 => ex_series
545+
.u64()?
546+
.fill_null_with_values(integer.try_into()?)?
547+
.into_series(),
548+
// We shouldn't ever call `Native.s_fill_missing_with_int/2` from the
549+
// Elixir side with a non-integer series.
550+
other => {
551+
panic!("s_fill_missing_with_int/2 implemented for integer types, found: {other:?}")
552+
}
553+
};
554+
555+
Ok(ExSeries::new(filled_series))
514556
}
515557

516558
#[rustler::nif(schedule = "DirtyCpu")]

test/explorer/series_test.exs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,10 @@ defmodule Explorer.SeriesTest do
608608
end
609609

610610
test "with integer" do
611-
s1 = Series.from_list([1, 2, nil, 4])
612-
assert Series.fill_missing(s1, 3) |> Series.to_list() == [1, 2, 3, 4]
611+
for integer_dtype <- Explorer.Shared.integer_types() do
612+
series = Series.from_list([1, 2, nil, 4], dtype: integer_dtype)
613+
assert Series.fill_missing(series, 3) |> Series.to_list() == [1, 2, 3, 4]
614+
end
613615
end
614616

615617
test "with float" do
@@ -856,6 +858,14 @@ defmodule Explorer.SeriesTest do
856858
"fill_missing with :neg_infinity values require a float series, got {:s, 64}",
857859
fn -> Series.fill_missing(s1, :neg_infinity) end
858860
end
861+
862+
test "with integer beyond accepted precision" do
863+
s1 = Series.from_list([1, 2, nil, 4], dtype: :s8)
864+
865+
assert_raise RuntimeError,
866+
"out of range integral type conversion attempted",
867+
fn -> Series.fill_missing(s1, 1_000) end
868+
end
859869
end
860870

861871
describe "equal/2" do

0 commit comments

Comments
 (0)