2.1.7 · D2Data Preprocessing & Feature Engineering

Visual walkthrough — Ordinal and target encoding

2,777 words13 min readBack to topic

Ordinal encoding was the easy sibling — you just line categories up in order and hand them the numbers . This page is about the harder, more interesting sibling: target encoding (we will abbreviate it TE once we have earned every piece of it).

Here is where we are headed — but read it only as a destination photo, not as something you should understand yet. Every symbol in it (the count, the two averages, the smoothing number) will be drawn from scratch in the steps below before we ever use it:

We are going to assemble it from absolutely nothing — no statistics assumed, no symbol used before it is drawn. By the end you will feel why that fraction is the only sensible shape it could have.

Back to the parent for the full picture: Ordinal and Target Encoding.


Step 1 — The problem: a column made of words

WHAT. We have a table. One column is a category (a word like NYC), and one column is the thing we want to predict — a number we will call the target, written (think "house price"). We will refer to the rows by a counter , so row has a category and a target .

WHY. A machine-learning model multiplies and adds numbers. It cannot multiply the word NYC. So a column of words is, to the model, invisible. We need to turn each word into a number — but not just any number: one that carries information about .

PICTURE. On the left, the raw table: a City column of words, a Price column of numbers. There is no arrow the model can draw from NYC to a price, because NYC is not on the number line at all.

Figure — Ordinal and target encoding

Contrast this with One-hot Encoding, which would spawn one new column per city. With 500 cities that is 500 mostly-zero columns. That blow-up in width is one face of the Curse of Dimensionality — more precisely, it makes each row a sparse point in a 500-dimensional space where distances lose meaning and models need far more data to learn; the curse is broader than "too many columns", but wide sparse encodings are a common way to walk into it. We want one column instead.


Step 2 — The first honest idea: replace each word with its group's average

WHAT. For a category , gather every row whose city is , and take the average of their targets. Call this , the "category mean". Then everywhere the word appeared, write .

WHY. If NYC rows are usually expensive, their average target is high; if Portland rows are usually cheap, their average is low. So the single number summarises what that word tells you about . That is exactly the signal we wanted to rescue from Step 1.

PICTURE. Each group of same-coloured dots (rows of one city) collapses onto a single horizontal level — its mean. NYC lands high, Portland lands low. The words have become positions on the number line.

Figure — Ordinal and target encoding

Term by term (recall is the row counter from Step 1):

Symbol
the category (word) sitting in row
Symbol
how many rows have category — the group's size
The condition
"for every row index whose word equals " — it selects the group
add up the targets of exactly those selected rows
divide by the group size, turning the sum into an average

Worked numbers (from the parent's Example 3): NYC has targets , so Likewise and .


Step 3 — Where the honest idea breaks: the group of one

WHAT. Look at Portland. It appears once, with target . Its "average" is just that single number, .

WHY it breaks. One data point is not a trend — it is a coin flip. If that one Portland house happened to be a mansion, its target would be huge, and we'd stamp Portland = huge forever. We are letting noise dress up as signal. A model that trusts this will overfit: it memorises a fluke instead of learning a pattern.

PICTURE. Two groups side by side. The NYC group (many dots, tightly clustered) has a mean we can trust — move any one dot and the average barely budges. The Portland group (a single lonely dot) has a mean that is entirely that one dot — move it and the mean flies with it. The error bars tell the story: wide for the lonely group, narrow for the crowded one.

Figure — Ordinal and target encoding

Step 4 — The safety net: the global mean

WHAT. Compute the average target over the entire training set, ignoring which city each row is. Call it .

WHY. When we don't trust a group's own average, we need a fallback — a "default guess" for a house price when the city tells us nothing reliable. The overall average is the least-biased default: it is what you'd predict knowing only "this is a house in the dataset".

PICTURE. All dots, every colour, pooled together; one dashed line runs through the whole cloud at their common average. This line is the anchor we will pull unreliable groups toward.

Figure — Ordinal and target encoding

Worked numbers. All six prices: .

(The parent's Example 3 uses a group-weighted phrasing — that equals the very same , because summing group-means-times-counts just re-adds the raw values.)


Step 5 — Blend the two: a slider between "own mean" and "safe mean"

WHAT. For each category, take a weighted average of its own mean and the global mean :

WHY a weighted average? Because it is the one shape that smoothly slides between our two known endpoints:

  • → trust the group fully → .
  • → trust the group not at all → .

The weights and sum to 1, so the result always lands between the two values — never overshooting either. That "sum to one" is what makes it an average and not just a random combination.

PICTURE. A slider. At the left end sits the global mean (safe); at the right end sits the group's own mean (risky but informative). The dot on the slider is the encoded value; is how far right it sits.

Figure — Ordinal and target encoding

Every symbol here (note finally spells out Target Encoding — the number that replaces the word):

the trust knob — how much weight we give the group's own mean, between 0 and 1
the leftover weight, automatically given to the safe global mean
the risky, informative group mean from Step 2
the safe fallback from Step 4

Step 6 — Choosing the knob: let the count decide

WHAT. We must pick . From Step 3 we already know the rule it must obey: big group ⇒ near 1; tiny group ⇒ near 0. The simplest formula that does exactly this is

WHY this exact fraction? Test it against the two demands:

  • Huge group, : the in the bottom becomes negligible, so . ✓ Full trust.
  • Empty/tiny group, : numerator , so . ✓ No trust.
  • And in between it rises smoothly from 0 to 1 as grows.

The number is the smoothing strength: it is the group size at which trust hits exactly one-half (). Small = trust groups quickly; large = stay cautious longer.

PICTURE. Plot against for a couple of values of . Each curve starts at 0, climbs steeply for small counts, then flattens toward 1. Mark the point where and .

Figure — Ordinal and target encoding

Step 7 — Substitute and simplify to the final formula

WHAT. Put into the blend of Step 5.

WHY. This turns two ideas — "weighted average" and "count-based trust" — into one closed formula we can compute directly.

Both terms share the denominator , so combine the numerators:

Reading the boxed formula as a story. The top is "the group's evidence ( rows saying ) plus pretend rows all saying ." The bottom is the total headcount, real plus pretend. It is just an average over voters, where of them are planted at the safe value. That is the empirical-Bayes trick in one line.

Term by term:

recovers the sum of the group's real targets (since )
the pseudo-rows' contribution, each worth the global mean
total number of voters, real () plus imaginary ()

PICTURE. A pan balance. On the pan sit real dots (weight ) tugging toward , and greyed pseudo-dots (weight ) tugging toward . The pointer settles at — closer to whichever side has more mass.

Figure — Ordinal and target encoding

Step 8 — Watch it work on every case

WHAT. Apply the boxed formula to all three cities, with and — matching the parent's Example 4 — its rounded global mean (the exact value from Step 4 is ; we use only to line up with the parent's arithmetic, as flagged in Step 4).

WHY. A formula you have only derived is still abstract. Running it on the lonely group, the crowded group, and the in-between group lets you see the smoothing behave differently in each — this is the moment the algebra turns into intuition, and it also lets us confirm the degenerate cases (tiny group, unseen group) do what Step 6 promised.

Portland (, ) — the lonely group: It got yanked almost all the way from up to the safe — exactly right, we didn't trust it.

NYC (, ) — the crowded group: It stayed much closer to its own side than Portland stayed to its own — because went to the global mean, leaving on the group. More data, more trust.

Seattle (, ):

PICTURE. Three horizontal arrows, one per city, each starting at the raw group mean and ending at the smoothed value, all bending toward the dashed global-mean line. The length of each arrow shrinks as the group grows — a visual proof that confidence buys independence.

Figure — Ordinal and target encoding

Note the encoded values () live on the target's scale (hundreds of thousands of dollars), so combine target encoding with Feature Scaling before feeding scale-sensitive models.


The one-picture summary

Figure — Ordinal and target encoding

This last figure stacks the whole journey: words → group means → a tug-of-war against the global mean, weighted by group size → the final smoothed number line. Read it top to bottom and you have re-derived the boxed formula.

Recall Feynman retelling — say it back in plain words

We started with a column of words, which a model can't do arithmetic on. So we replaced each word with the average target of its group — expensive cities get a high number, cheap ones a low number. Great, except a group with only one row gives an average that's really just noise pretending to be a pattern. To fix that, we found a safe fallback: the average over everyone. Then we said "blend the group's own average with the safe one," using a weighted average so the answer always lands between them. The weight had to obey one rule — trust big groups, distrust tiny ones — and the simplest formula for that is , which is 1 for huge groups and 0 for empty ones. Substituting it and cleaning up gives : literally an average over the real rows plus imaginary rows glued to the safe value. Big groups drown out the imaginary rows and keep their own opinion; tiny groups get overruled and slide back to safe. And a brand-new, never-seen category has zero real rows, so it just returns the safe average — the formula handles it for free.

Recall

Why does approach 1 for large groups? ::: The becomes negligible next to a huge , so the fraction — full trust in the group's own mean. What is the encoding for a category unseen in training? ::: , because collapses the formula to . In one sentence, what does represent? ::: The number of pseudo-observations pinned at the global mean — the group size at which trust is exactly one-half. How should you choose in practice? ::: Treat it as a hyperparameter — try several values and pick the best held-out score under cross-validation, starting near the typical group size.