Add ColumnArithmetic, ColumnConcat and TypeCast converters#770
Open
Felipedino wants to merge 12 commits into
Open
Add ColumnArithmetic, ColumnConcat and TypeCast converters#770Felipedino wants to merge 12 commits into
Felipedino wants to merge 12 commits into
Conversation
…aching improvements
…ded dataset (all original columns) instead of the input-only
… and type detection
…g and missing value normalization
- Implemented NumericExpansion converter to apply unary operations (log1p, square, sqrt) on numeric columns. - Added NumericExpansionSchema for hyperparameter validation. - Updated initial_components.py to include NumericExpansion. - Introduced BalancedAccuracy metric for improved classification performance evaluation. - Enhanced various classifiers (DecisionTree, ExtraTrees, HistGradientBoosting, etc.) with class_weight parameter to handle class imbalance. - Updated classification_task to support BalancedAccuracy. - Added tests for BalancedAccuracy to ensure correctness against sklearn reference.
- Implemented ColumnConcat for concatenating string columns with optional constant and separator. - Added TypeCast for changing column types with error handling options. - Updated initial_components to include new converters.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR expands DashAI’s tabular pipeline capabilities by introducing new feature-engineering converters (arithmetic, concatenation, numeric expansion) and a pipeline-time type casting converter, while also adding new classification models/metrics and improving sklearn-wrapper behavior around missing values.
Changes:
- Adds new simple converters:
ColumnArithmetic,ColumnConcat,NumericExpansion, andTypeCast(feature engineering + in-pipeline type conversion). - Adds new ML components:
XGBClassifier,LGBMClassifier, andBalancedAccuracy, including registration and test coverage for the new model/metric. - Improves conversion/pipeline infrastructure: normalizes missing values passed to sklearn transformers, adds a small fit→transform pandas cache, and optimizes/clarifies converter-job dataset rebuilding and scoping.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/back/models/test_tabular_class_models.py | Extends classifier smoke tests to cover new XGBoost/LightGBM model wrappers. |
| tests/back/metrics/test_classification_metrics.py | Adds tests for the new BalancedAccuracy metric (including sklearn reference comparison). |
| pyproject.toml | Adds lightgbm and xgboost runtime dependencies. |
| DashAI/back/tasks/classification_task.py | Registers BalancedAccuracy as compatible with classification tasks. |
| DashAI/back/models/scikit_learn/xgboost_classifier.py | Introduces XGBClassifier component + schema and DashAI mixin workaround for XGBoost MRO assumptions. |
| DashAI/back/models/scikit_learn/lightgbm_classifier.py | Introduces LGBMClassifier component + schema and DashAI mixin workaround for LightGBM MRO assumptions. |
| DashAI/back/models/scikit_learn/svc.py | Adds class_weight support to SVC schema. |
| DashAI/back/models/scikit_learn/sgd_classifier.py | Adds class_weight support to schema and forwards it into the underlying raw estimator. |
| DashAI/back/models/scikit_learn/random_forest_classifier.py | Adds class_weight schema field for RandomForestClassifier. |
| DashAI/back/models/scikit_learn/logistic_regression.py | Adds class_weight schema field for LogisticRegression. |
| DashAI/back/models/scikit_learn/linear_svc_classifier.py | Adds class_weight schema field and forwards it into the underlying raw estimator. |
| DashAI/back/models/scikit_learn/hist_gradient_boosting_classifier.py | Adds class_weight schema field for HistGradientBoostingClassifier. |
| DashAI/back/models/scikit_learn/extra_trees_classifier.py | Adds class_weight schema field for ExtraTreesClassifier. |
| DashAI/back/models/scikit_learn/decision_tree_classifier.py | Adds class_weight schema field for DecisionTreeClassifier. |
| DashAI/back/metrics/classification/balanced_accuracy.py | Adds the BalancedAccuracy classification metric implementation. |
| DashAI/back/job/predict_job.py | Adjusts how prediction outputs are merged/saved (drop any existing output column before adding predictions). |
| DashAI/back/job/converter_job.py | Optimizes dataset rebuild logic and avoids redundant column selection when no row-level scope is set. |
| DashAI/back/initial_components.py | Registers the new converters, models, and metric in the initial component set. |
| DashAI/back/converters/sklearn_wrapper.py | Normalizes missing values for sklearn, and caches the fit input DataFrame for reuse in transform when possible. |
| DashAI/back/converters/scikit_learn/simple_imputer.py | Improves output type preservation based on strategy/statistics; adds fit-time bookkeeping for typing. |
| DashAI/back/converters/category/feature_engineering.py | Adds a converter category base class for “Feature Engineering” converters. |
| DashAI/back/converters/simple_converters/column_arithmetic.py | Adds ColumnArithmetic converter (scope-derived operands + constant mode). |
| DashAI/back/converters/simple_converters/column_concat.py | Adds ColumnConcat converter (scope-derived operands + constant mode). |
| DashAI/back/converters/simple_converters/numeric_expansion.py | Adds NumericExpansion converter (log1p/square/sqrt derived columns). |
| DashAI/back/converters/simple_converters/type_cast.py | Adds TypeCast converter reusing dataset-upload type validation logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…gineeringConverter and NumericExpansion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add ColumnArithmetic, ColumnConcat and TypeCast converters
Summary
ColumnArithmeticso operands are derived from the columns selected in scope instead of typed column names, and fixes a silent data-corruption bug in its integer path.ColumnConcat, a new converter for concatenating string columns.TypeCast, a new converter for changing a column's DashAI type from within a pipeline, reusing the same validation used by the dataset upload preview.Motivation
ColumnArithmeticrequired the user to (1) select a scope of columns in the pipeline builder UI, and then (2) separately type the exact column names intocolumn_a/column_btext fields — completely redundant, since the converter'sfit()already receives only the scoped columns. This PR removes that redundancy across the whole "binary operand" converter family (arithmetic and the new concat converter), and adds a way to change column types mid-pipeline that previously only existed in the dataset-upload preview screen.Changes
ColumnArithmetic(redesigned)column_a,column_b, andoperand_b_modeare no longer schema parameters. Operands are now derived from the columns selected in scope duringfit():ConverterJob).constantparameter.swap_operandsboolean lets the user reverse the two-column order (relevant forsubtract/divide, which aren't commutative).metadata.input_cardinality = {"min": 1, "max": 2}reuses the existing explorer mechanism to constrain the frontend's column selector to 1–2 columns, so no frontend changes are required.Integerand either has a missing value,transform()previously cast the underlyingNaNtoint64via.to_numpy(dtype="int64"), which numpy silently converts to the sentinel-9223372036854775808instead of raising or propagating a null.fit()now checksnull_counton the operand columns and falls back to theFloatoutput path (where missing values propagate correctly asNaN) whenever either operand has missing values.constantofNaNorInfinity(reachable via direct API calls, not the browser UI) previously passed validation and then crashed with a confusing low-levelValueError/OverflowErrorfromint(nan). Now explicitly rejected with a descriptive message.ColumnConcat(new)ColumnArithmetic's scope-driven design: 2 columns → join them; 1 column → join with aconstantstring.separatorinserted between the two operands (none by default).swap_operandsto reverse concatenation order, same asColumnArithmetic.None.metadata.allowed_types = [Text, Categorical].TypeCast(new)new_type(Integer,Float,Text, orCategorical), reusingDashAI.back.types.type_validation.validate_type_change— the exact same validation and conversion logic used by the/datasets/validate_type_changesendpoint behind the upload preview screen, so behavior is consistent between upload-time and pipeline-time type changes.on_errorcontrols behavior when a column can't be safely converted (e.g. non-numeric text targetingInteger):"raise"(default) stops with a descriptive, column-specific error;"skip"leaves that column unchanged, prints a warning, and continues with the rest of the columns in scope.fit()and reuses it intransform()when called with the same dataset (the common case), instead of recomputing the full validation/conversion pass twice.NumericExpansion(fixed, pre-existing converter)ColumnArithmeticfix above —squareon anIntegercolumn with missing values previously kept the declared output type asIntegerwhiletransform()cast the underlyingNaNto theint64sentinel via.to_numpy(dtype="int64")and squared it, silently producing garbage.fit()now checksnull_counton the source column and falls back toFloatoutput whenever it has missing values.FeatureEngineeringConverter(docstring only)ColumnConcat(Text output) belongs to the same category.Registration
ColumnConcatandTypeCastregistered inDashAI/back/initial_components.pyalongside the existing simple converters.Design notes / trade-offs
ConverterJob) resolves a scope's columns in ascending dataset-column-index order, not the order the user selected them in the UI — this is a pre-existing, unchangeable platform behavior (confirmed not just for these converters but for the whole scope-selection mechanism used by explorers too).swap_operandsis the chosen mitigation: a simple, low-risk escape hatch rather than a deeper fix to the shared column-selection component, which would carry more risk and affect every converter/explorer using scope selection.ColumnArithmetic's oldcolumn_a/column_b/operand_b_modeconstructor signature. This converter was introduced and rewritten within the same development cycle and was never released, so there is no persisted data to migrate.column_aandcolumn_b) is no longer directly expressible, since a scope can't contain the same dataset column twice. This was a capability of an unreleased draft, not a shipped feature.Testing
No automated tests were added in this PR.
tests/back/converters/only covers converter metadata (test_base_converter_metadata.py); there is no test file forsimple_converters/— this is a pre-existing gap in the codebase, not something this PR fixes.What was actually done to validate the changes: manual, ad hoc verification scripts run locally against real
DashAIDatasetinstances during development (not committed as test files). These covered:ColumnArithmetic: 2-column add/subtract (with and withoutswap_operands), 1-column + constant, integer-preserving output when no missing values,Floatfallback with correctNaNpropagation when a missing value is present, rejection of out-of-range column counts, rejection ofNaN/Infinityconstants.ColumnConcat: 2-column concatenation with a separator and null propagation, 1-column + constant (including an empty-string constant),swap_operands.TypeCast: Text→Integer/Float/Categorical, Float→Integer rejection on decimal loss (bothraiseandskipmodes), no-op on already-matching type, and confirmed (via call-count instrumentation) thattransform()reusesfit()'s cached conversion when given the same dataset, falling back to a fresh conversion when given a different one.NumericExpansion:squareon anIntegercolumn with a missing value now falls back toFloatwith correctNaNpropagation, and still returnsIntegerwhen there are no missing values.ruff check/ruff formatpass clean on all changed/added files.Follow-up work should add real
pytestcoverage undertests/back/converters/simple_converters/for this converter family.Follow-ups (not in this PR)
simple_converters/(see Testing section above).column_arithmetic.png,column_concat.png,type_cast.png) exist yet inDashAI/back/static/images/for these converters.ColumnArithmetic.fit()andColumnConcat.fit(). Left un-extracted for now (only two instances, with different per-type validation), but worth revisiting if a third "binary operand from scope" converter is added.