Dataco turns Moroccan housing scrapes into a repeatable learning pipeline
Dataco pairs a batch validation workflow for Moroccan housing listings with an incremental training path that can process newly scraped records without rebuilding its preprocessing step.
A housing model needs a path from scrape to update
A property-price model is rarely useful as a one-off notebook. Listings change, new records arrive, and the data preparation choices made during an experiment must remain consistent once a model starts receiving fresh batches. Dataco, a project by MuLIAICHI, is structured around that practical handoff.
The repository documents Moroccan housing price prediction using listing data scraped from Mubawab.ma through a custom Apify actor. Its stated goal is an end-to-end machine learning project inspired by Chapter 2 of Hands-On Machine Learning. More specifically, it separates validation work from incremental updates: first evaluate a conventional batch pipeline, then maintain an online model as new listings become available.
That makes the project relevant to builders who want to move beyond a static regression exercise without claiming that every new data source requires a complete retraining workflow. It is also a useful concrete example of how to preserve preprocessing state when an incremental estimator is used.
Two phases, with different jobs
The first phase lives in a validation notebook, notebooks/morocco_housing_ml.ipynb. According to the README, it follows a batch machine learning workflow: it creates a stratified train and test split based on city, adds custom ratio features through a MoroccanFeatureAdder transformer, and prepares mixed columns with a ColumnTransformer.
That preparation includes median imputation for missing values, one-hot encoding for categorical values, and feature standardization. Median imputation fills a missing numeric value with the median from the relevant column. One-hot encoding converts a category into indicator columns, while standardization brings numeric features onto comparable scales. These steps are especially consequential when a model will later see batches that must be transformed in exactly the same way.
The notebook evaluates Linear Regression, Decision Tree, and Random Forest models. The documented evaluation approach uses five-fold cross-validation and RandomizedSearchCV, a search method that samples model-parameter combinations rather than exhaustively trying every possibility. The README reports MVP cross-validation RMSE values from March 2026: 2.90M MAD for Linear Regression, 5.45M MAD for the Decision Tree, and 3.55M MAD for Random Forest. RMSE, or root mean squared error, expresses prediction error in the target's units and weights larger mistakes more heavily.
Those figures are best read as the repository's documented validation snapshot, not as a general claim about Moroccan housing prices or model quality. The README also reports a median listing price of 1.25M MAD, which provides some context for the scale of the target and the reported errors.
An incremental path for new listings
The second phase, src/online_learning.py, is designed for updates after the initial validation work. It uses SGDRegressor.partial_fit(), an interface for incrementally fitting a linear regression model with successive batches. In local development mode, the script can read the supplied CSV. In its production-oriented path, it fetches new listings from an Apify Dataset API.
The repository describes the retrieval as offset-based, so the script can pick up from the last processed position and avoid training on duplicate rows. It stores runtime state in a gitignored model_state/ directory, including a preprocessor artifact, a model artifact, and state.json. The README describes this state as auto-created at runtime.
The most important design decision is explicit: after cold start, the preprocessor is frozen and is not re-fit. This avoids a subtle mismatch between past and future feature representations. If category mappings, imputation values, or scaling parameters changed each time a batch arrived, the model would receive features defined on shifting scales or columns. Keeping the preprocessor fixed makes each new batch compatible with the representation used to fit the existing online model.
There is a tradeoff. A frozen preprocessor also means that changes in the incoming data, such as new categories or a materially different distribution, are not incorporated by refitting that preparation stage. Dataco does not present that as a solved problem, but its README does identify future work around neighbourhood target encoding, location enrichment, a log transform for the right-skewed price_dh target, and additional model benchmarks.
A benchmark keeps the update path accountable
An online update path should not be treated as automatically equivalent to the best batch model. Dataco includes a --benchmark option that compares the online model with Random Forest on a held-out test set. That is a practical safeguard: the model chosen for easy incremental updates, SGDRegressor, has a different learning approach from the tree-based Random Forest evaluated in the notebook.
The comparison makes the operational tradeoff visible. A batch Random Forest can be evaluated during the validation phase, while the online model can absorb new batches with partial_fit(). The repository gives users a way to inspect their relative results rather than assuming the online path is better simply because it is easier to update.
For operation, the documented commands also cover an incremental rerun and a --reset option for a full restart. Production use requires setting an Apify API token and dataset name or ID in the script's configuration block. The README cautions against committing the token and points to environment variables or a .env file as alternatives.
The confirmed toolkit
The repository metadata identifies TypeScript as its primary language, while the documented modeling workflow itself is run with Python commands and Python packages. The README's installation instructions name NumPy and pandas for numerical and tabular work, scikit-learn for preprocessing, model fitting, cross-validation, and search, Matplotlib for plotting, joblib for persisted model state, and requests for HTTP access. Apify provides the documented dataset API source for incoming listings.
Dataco's value is not a claim of a finished production pricing system. It is a clear project layout for connecting a scraped listing dataset, batch validation, persisted preprocessing, and incremental model updates. Builders exploring similar pipelines can inspect the notebook and update script to see where those boundaries are drawn, then adapt the choices to their own data and evaluation needs.
Explore the verified repository at github.com/MuLIAICHI/Dataco.
Turn your GitHub repository into a story worth sharing.
Connect a public repository, generate a reviewable draft, and publish it with Reather.
