← Back to Data Exploration with rakoon-ds
Practical Work 6

Data quality in depth: holes, duplicates, outliers, identifiers, leaks

Everything the Quality tab tells you, what it cannot tell you, and the ten points of accuracy that were hiding in 240 duplicate rows

Duration 75 min
Level Intermediate
Session Session 6
Mission dep-6

Objectives

By the end of this session you will be able to:

  • Read a missing-value pattern and turn it into a hypothesis about the data collection
  • Measure what duplicate rows do to a score, instead of assuming
  • Compare the two outlier methods and choose one on purpose
  • Recognise an identifier column and know why the studio drops some columns by itself
  • Name the five leak codes rakoon-ds raises, and find one it does not raise
  • Seal a test set before you have the chance to peek

Prerequisites

  • A rakoon-ds account on https://rakoon-ds.apps.way-up.io (free, browser only, nothing to install), and the group join code your instructor gives you
  • A recent Chrome, Edge or Firefox. Computation runs either in your own tab (browser engine) or on the server; the header pill tells you which
  • The mission for this session, assigned to your group. Open a project, then the Mission button in the workshop header: the panel opens next to Report. Click Check after each step
  • Practical works 1 and 2 finished
  • Transformation, chart and algorithm names come from the rakoon-ds registry and are served in French even when the interface is in English. Every step below gives you the French label you will click and, in code font, the registry key the mission checks against.

Data

Three built-in datasets, each chosen for one defect. Nothing to download.

DatasetRows x colsThe defect it carries
titanic1 309 x 1120 % of ages missing, 77 % of cabins missing, and the two go missing together
wine_quality1 599 x 12240 exact duplicate rows and a target imbalanced 68 to 1
bike_sharing731 x 15two columns whose sum is exactly the target

If your instructor gives you the SNCF lost-property pack (objets-trouves-restitution-2019 to -2022, 258 902 rows), run the same six steps on it: the return date is the leak, and the studio flags it as leak_association at 1.00 with an accuracy of 0.999, against 0.70 for the honest model.

Timing

The steps below add up to the announced duration. If you fall behind, Step 1 to Step 3 are the ones that must be finished.

#What you doTime
Step 1Missing values, and the pattern block nobody reads12 min
Step 2Duplicates: measure them, do not assume15 min
Step 3Outliers: two methods, two viewpoints12 min
Step 4Identifiers, and what the studio drops behind your back10 min
Step 5Leaks: the five it catches, and the one it misses16 min
Step 6Seal, and write the data section10 min
Total75 min

Instructions

Step 1: Missing values, and the pattern block nobody reads12 min

  1. New project PW6 Quality. Add the built-in Titanic (passagers).
  2. ExploreQuality, target survivant.
  3. In the Missing values card, read the per-column bars, then scroll to Most frequent patterns.

Reference figures: age 263 missing (20.1 %), cabine 1 014 (77.5 %), canot 823 (62.9 %). And the patterns:

Columns empty togetherRowsShare
cabine + canot53841.1 %
cabine alone23518.0 %
age + cabine + canot18213.9 %
canot alone906.9 %

Answer in writing, in two sentences: what kind of passenger is described by the first pattern, and what does that imply about imputing age with the overall mean?

The card of this dataset says it: age is missing more often in third class. Dropping incomplete rows therefore deletes third class preferentially, and imputing with the mean makes every third-class passenger look like an average passenger. Neither is neutral. "Missing" is data.

Step 2: Duplicates: measure them, do not assume15 min

  1. Add the built-in Qualité du vin rouge (wine_quality).
  2. Quality tab, target qualite. The Duplicates card reports 240 extra rows (15.0 %), 220 groups, 1 359 distinct rows, and lists the row numbers of each group.
  3. Train a Forêt aléatoire (rf_clf) on qualite with every column. Note the accuracy.
  4. Apply Supprimer les doublons (drop_duplicates) (family Lignes, no column selected = all columns). You get 1 359 rows.
  5. Train the same forest on the deduplicated dataset. Note the accuracy again.
DatasetRowsAccuracyF1
wine_quality as delivered1 5990.67250.6506
after drop_duplicates1 3590.57060.5504

Ten points of accuracy. They were not skill, they were the same wine sitting on both sides of the train / test split: the model recognised rows it had already been shown. This is the cheapest and most common way to lie to yourself with a score.

Also read the Class balance card here: 681 wines rated 5, 10 wines rated 3, a majority-to-minority ratio of 68.1, and three classes flagged rare (4 with 53 rows, 8 with 18, 3 with 10). What does global accuracy tell you about a class that holds 0.6 % of the data?

Step 3: Outliers: two methods, two viewpoints12 min

Still on wine_quality, Outliers card. Each numeric column gets two counts side by side: outside the Tukey (IQR) bounds, and |z| > 3. Plus the bounds, the quartiles, and up to five example values with their row number.

ColumnOutside IQR bounds
sucre_residuel155
chlorures112
sulfates59
so2_total55
acidite_fixe49
  1. Pick sucre_residuel. Click through to two of the example rows in Overview. Are they errors, or are they sweet wines?
  2. Decide, and act: keep them, cap them with Filtrer des lignes (filter_rows), or bin them with Discrétiser (bins) (bin_numeric) so the extreme values fall into one bucket.
  3. Write down the decision and the reason. "I removed the outliers" is not a reason.

The interquartile method assumes nothing about the shape of the distribution; the z-score assumes it is roughly normal. On a skewed column they disagree, and the disagreement is the information. The report looks at one column at a time: a point that is only strange through the combination of its values is not seen at all.

Step 4: Identifiers, and what the studio drops behind your back10 min

A column with almost as many distinct values as rows cannot generalise. rakoon-ds does two things about it, and you need to know both.

  1. On titanic, Quality tab: nom is listed under the points to watch, 1 307 distinct values out of 1 309, ratio 0.998.
  2. Train any classification model on titanic and open its results. Look for the list of variables actually used.
  3. You will find that nom and cabine were disabled automatically and that the studio says so.

That is a real difference with Orange, where a one-hot encoding of 1 307 names explodes in your face. Here the columns are excluded and the list is shown. Your job is no longer to survive the explosion, it is to read the list and check that nothing useful was dropped.

One subtlety worth remembering: a continuous column whose values are all distinct is not treated as an identifier. Three random coordinates are not three row numbers. Only text, categorical and integer columns can be flagged.

Step 5: Leaks: the five it catches, and the one it misses16 min

rakoon-ds checks for leaks before training and shows a banner above the metrics. Five codes:

CodeSeverityWhat it means
leak_duplicatehighthe column is the target: same values, or a bijective recoding of it
leak_associationhighmixed association with the target at 0.98 or more
leak_nameto fixthe column name contains the target name (prix_final_estime when predicting prix)
id_featureto fixa near-unique feature column
constant_targethighthe target is constant, or 99 % one class

Now the counter-example. Add the built-in Vélos en libre-service (par jour) (bike_sharing). Its card says that occasionnels plus abonnes equals total, exactly.

  1. Train a Forêt aléatoire (rf_reg) on total with every column.
  2. Reference result: R² = 0.9974, RMSE 99.8, and no warning at all.

The detector looks at one column against the target. Neither occasionnels nor abonnes alone reaches the 0.98 threshold, so nothing fires, and the model is still doing an addition rather than a prediction. A leak that is spread across two columns is invisible to the tool. That is what the model card, and you, are for.

  1. Retrain without occasionnels and abonnes. Reference: R² 0.8889 with the calendar and weather columns, against R² -0.0245 for the Modèle de référence (médiane) (dummy_reg).
  2. Write both numbers down. One of them is a fact about the world; the other is a fact about your spreadsheet.

Step 6: Seal, and write the data section10 min

  1. On any of the three datasets: apply Découper (proportions) (split) with 0.8, 0.2 to get two disjoint parts.
  2. Click the 20 % node and press Sceller. Try to open Explore on it: preview, profile, quality, charts and download all answer with a padlock and one sentence.
  3. Train a model on the 80 % part, choosing the sealed node as Jeu de test. It works: the sealed dataset is still a perfectly valid test set.

Write as you go, not at the end. In the Report panel every section has its guiding questions in grey; anything you type is saved after 0.7 s. Write the Données section: for each of the three datasets, the defect, the number, and what you did about it. Fifteen lines.

If a browser-side training uses a sealed test set, the computation falls back to the server, because downloading the sealed file is exactly what sealing forbids. Same result, different machine, and the header pill says so.

What you should have

  • A missing-value pattern read and interpreted, not just observed
  • The duplicate experiment run: two numbers, ten points apart
  • An outlier decision taken and justified on one column
  • The list of automatically disabled columns, found and read
  • The bike leak reproduced: R² 0.9974 with no warning
  • One sealed dataset used as a test set
  • The dep-6 mission at 6 / 6

Deliverables

  • Mission: dep-6 validated
  • Report: Données and Exploration sections, with the before / after duplicate table
  • One paragraph: name a leak that rakoon-ds would not catch on a dataset from your own field, and say how you would catch it

Bonus

  • On breast_cancer, the thirty variables are highly redundant (radius, perimeter and area describe the same size). Look at what that does to the permutation importance chart: importance shared between twins looks like importance that does not exist.
  • Build a CSV where one column is the target recoded 0 / 1, import it, train, and see leak_duplicate fire.
  • Rename a column to total_estime on bike_sharing and train on total: leak_name should fire on the name alone.

Resources