Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/perf-regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- name: Install
run: |
python -m pip install -U pip
pip install -e ".[bench]"
pip install -c constraints/ci.txt -e ".[bench]"
- name: Resolve base commit
id: base
env:
Expand Down
8 changes: 3 additions & 5 deletions docs/community/contributor-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@ review does not depend on understanding the whole cleaning pipeline.
[Great Expectations recipe (#8)](https://github.com/FreshCode-Org/freshdata/issues/8),
[ydata-profiling comparison (#7)](https://github.com/FreshCode-Org/freshdata/issues/7).
Files live in [`examples/`](https://github.com/FreshCode-Org/freshdata/tree/main/examples).
- **Small isolated cleanups** —
[de-duplicate `_has_outliers` (#33)](https://github.com/FreshCode-Org/freshdata/issues/33)
and
[fix boolean coercion in `_coerce_series` (#31)](https://github.com/FreshCode-Org/freshdata/issues/31)
are both labeled `good first issue` and name the exact function and file.
- **Small isolated cleanups** — look for open issues labeled
[`good first issue`](https://github.com/FreshCode-Org/freshdata/labels/good%20first%20issue);
each names the exact function and file.

**Skills:** Python, pandas basics. **You'll touch:** `examples/`, `docs/`, or one
named module + its test.
Expand Down
5 changes: 4 additions & 1 deletion src/freshdata/imputation/missforest.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,10 @@ def _convergence_delta(
if plan.model_type == "regressor":
prev_num = pd.to_numeric(prev, errors="coerce")
cur_num = pd.to_numeric(cur, errors="coerce")
denom = float(np.nanstd(cur_num.to_numpy(dtype="float64"))) or 1.0
# na_value: nullable (masked) columns with missing cells refuse a
# plain float64 conversion on pandas < 2.
values = cur_num.to_numpy(dtype="float64", na_value=np.nan)
denom = float(np.nanstd(values)) or 1.0
deltas.append(float(np.nanmean(np.abs(cur_num - prev_num))) / denom)
else:
deltas.append(float((cur.astype(object) != prev.astype(object)).mean()))
Expand Down
13 changes: 13 additions & 0 deletions tests/test_missforest_imputation.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,16 @@ def test_missforest_auto_indicator_uses_prefill_informative_missingness():

assert "age_was_missing" in out.columns
assert int(out["age_was_missing"].sum()) == 40


def test_missforest_handles_nullable_integer_column_with_missing_values():
# Regression: pandas < 2 refuses a plain float64 conversion of a masked
# (nullable) integer column that still holds missing values.
df = _mixed_frame()
df["age"] = pd.array(df["age"].round().astype(int), dtype="Int16")
df.loc[5:14, "age"] = pd.NA

out, report = fd.clean(df, impute="missforest", return_report=True, **ISOLATE)

assert out["age"].isna().sum() == 0
assert _missforest_actions(report, "age")
Loading