From 616ac7ef461c8225c3765c3dac51eccefe2126cb Mon Sep 17 00:00:00 2001 From: "Clelia (Astra) Bertelli" Date: Wed, 8 Apr 2026 10:27:59 +0200 Subject: [PATCH 1/2] feat: support custom values in fillNull --- __test__/index.spec.ts | 20 +++++++++++++++++++- index.d.ts | 7 ++++++- src/lib.rs | 20 +++++++++++++++----- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/__test__/index.spec.ts b/__test__/index.spec.ts index b4a4967..d80743b 100644 --- a/__test__/index.spec.ts +++ b/__test__/index.spec.ts @@ -227,7 +227,7 @@ test('Reading null values works correctly', (t) => { t.deepEqual(col4, [true, false, true, false, null]) }) -test('Filling null values works correctly', (t) => { +test('Filling null values with zero values works correctly', (t) => { const df = readCsv('testfiles/with-nulls.csv') df.fillNull() t.is(df.len, 5) @@ -245,6 +245,24 @@ test('Filling null values works correctly', (t) => { t.deepEqual(col4, [true, false, true, false, false]) }) +test('Filling null values with custom values works correctly', (t) => { + const df = readCsv('testfiles/with-nulls.csv') + df.fillNull('test', 99.3, 77, true) + t.is(df.len, 5) + const col1 = asStringArray(df.get('col1')!)! + t.is(col1.filter((x) => x === null).length, 0) + t.deepEqual(col1, ['hello', 'test', 'bye', 'test', 'ciao']) + const col2 = asIntArray(df.get('col2')!)! + t.is(col2.filter((x) => x === null).length, 0) + t.deepEqual(col2, [1, 2, 77, 3, 4]) + const col3 = asFloatArray(df.get('col3')!)! + t.is(col3.filter((x) => x === null).length, 0) + t.deepEqual(col3, [0.1, 0.2, 0.3, 99.3, 0.4]) + const col4 = asBooleanArray(df.get('col4')!)! + t.is(col4.filter((x) => x === null).length, 0) + t.deepEqual(col4, [true, false, true, false, true]) +}) + test('Dropping NaN values works correctly', (t) => { const col1 = toStringColumn(['hello', 'world', null, 'bye', 'moon', 'hey']) const col2 = toFloatColumn([1.2, 2.3, 0.3, NaN, 0.5, 8.9]) diff --git a/index.d.ts b/index.d.ts index 529dea2..04e341a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -10,7 +10,12 @@ export declare class DataFrame { dropNan(): void fillNan(fillValue?: number | undefined | null): void dropNull(): void - fillNull(): void + fillNull( + fillString?: string | undefined | null, + fillFloat?: number | undefined | null, + fillInt?: number | undefined | null, + fillBool?: boolean | undefined | null, + ): void writeCsv(path: string): void } diff --git a/src/lib.rs b/src/lib.rs index 66e8c8f..f906528 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -343,34 +343,44 @@ impl DataFrame { } #[napi] - pub fn fill_null(&mut self) { + pub fn fill_null( + &mut self, + fill_string: Option, + fill_float: Option, + fill_int: Option, + fill_bool: Option, + ) { + let str_val = fill_string.unwrap_or_default(); + let f64_val = fill_float.unwrap_or_default(); + let i64_val = fill_int.unwrap_or_default(); + let bool_val = fill_bool.unwrap_or_default(); for col in self.columns.values_mut() { match col { ColumnData::Boolean(b) => { for item in b.iter_mut().take(self.len as usize) { if item.is_none() { - *item = Some(false); + *item = Some(bool_val); } } } ColumnData::Float(f) => { for item in f.iter_mut().take(self.len as usize) { if item.is_none() { - *item = Some(0_f64); + *item = Some(f64_val); } } } ColumnData::String(s) => { for item in s.iter_mut().take(self.len as usize) { if item.is_none() { - *item = Some(String::new()); + *item = Some(str_val.to_owned()); } } } ColumnData::Integer(j) => { for item in j.iter_mut().take(self.len as usize) { if item.is_none() { - *item = Some(0_i64); + *item = Some(i64_val); } } } From 9e0cf3c8faf96cefc7500d1a89535d9e6d756a5d Mon Sep 17 00:00:00 2001 From: "Clelia (Astra) Bertelli" Date: Wed, 8 Apr 2026 10:30:28 +0200 Subject: [PATCH 2/2] docs: update readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index bef6358..d725390 100644 --- a/README.md +++ b/README.md @@ -114,10 +114,9 @@ The DataFrame class supports also methods for filtering out or changing null val const df = readCsv('test.csv') df.dropNull() // drop null df.fillNull() // fill null values with the zero value of their type +df.fillNull('a string', 0.5, 4, true) // fill null values with custom values ``` -> NOTE: `fillNull` works with zero values, which means: `""` for string, `0` for integer and float, `false` for boolean - You can filter out and change NaN values as well (only applies if there are float-typed columns): ```typescript