skip to content

A report averages the amount column of a table holding one row per measurement across six measures and returns a meaningless number — why?

level: seniorimportance: should knowfreq 46%

answer

  1. meaning lives in the row, not the header
  2. one column, six units
  3. the aggregate never named a quantity
  4. condition on the name column first
  5. well formed, silent, and wrong

basics

~20 s

Because a cell's meaning comes from its row's name column, not from the column it sits in: one value column holds six quantities in six units. Any aggregate that does not condition on the name column mixes them.

solid answer

~50 s

In this arrangement the semantics of a number live in the row, not in the header. The value column is a union of six different quantities, with different units and different scales, so a mean over it adds footfall to revenue to a returns count and divides by however many rows happened to arrive. The result is not merely imprecise, it has no unit. The same fault wears other clothes: a maximum returns whichever measure is numerically largest, a total is a sum of unlike things, a row count counts measurements rather than subjects, and a per-subject mean is weighted by how many measurements each subject happens to have. The fix is to condition on the name column for every read, and to treat a bare aggregate over a value column as a defect when you review one.

go deeper

for a junior

Take away one rule: never aggregate a value column without first saying which measure the rows are about.

for a middle

Explain why the computation succeeds while being wrong — the cells are numbers, the aggregate is valid, and only the unit was never checked.

for a senior

Diagnose the family, not the instance: maxima, totals, row counts and per-subject means all fail the same way, and a selection that matched nothing fails quietly on top.

for a principal

Decide what the team's standing rule is. Requiring every published figure to trace to a named measure is a review discipline, not something the arrangement enforces for you.

## Why the number is meaningless In a table with one row per measurement, a cell's meaning is supplied by its row's name column, not by the column it sits in. The value column is therefore a union: footfall in people, revenue in currency, returns in items, a temperature in degrees. A mean over that union adds quantities that have no common unit and divides by a row count that depends on which measures happened to arrive. Nothing about it is salvageable by rounding or by a larger sample. It is not an imprecise number, it is a number with no unit. The reason it went unnoticed is that the computation is perfectly well formed. The column exists, its cells are numbers, an aggregate over numbers returns a number. There is no failure to catch, which is exactly why this shows up in a finished report rather than in a stack trace. ## The same fault in other clothes - **A maximum or a minimum** over the value column returns whichever measure is numerically largest or smallest, which is a fact about units rather than about the business. - **A total** is a sum of unlike things and behaves like one: it moves whenever the mix of measures changes, even if nothing measured changed. - **The table's row count**, read as a count of subjects, is wrong by roughly the number of measures per subject. It counts measurements. - **A per-subject mean of the value column** has the unit problem *and* a weighting problem: subjects with more measurements pull the answer, so the result is weighted by measurement count rather than by subject. - **A distribution or a spread** computed over the union describes the mixture of measures, not the variability of any one of them. ## Where the trap comes from With one column per measure, the semantics of a number are carried by the header. An aggregate names a column, and in naming the column it has already named the quantity; a column holding two different units cannot arise by accident. Naming a measurement in a cell moves that semantics one column sideways, so naming the value column names nothing at all. Every aggregate silently acquires a precondition — *which rows?* — that the code has no way to make you state. That is the property to articulate in an interview: this arrangement trades a schema that cannot change for a semantics that is not enforced anywhere. ## Conditioning on the name column The repair is mechanical, and the discipline around it is the interesting part: 1. **Select the rows for one measure, then aggregate, and repeat per measure.** Every figure in the report is then a figure about a named quantity. 2. **Match the name to what the producer actually emits.** A measure that was renamed, or split into two names, still yields rows and still yields a plausible number — just over fewer rows than you think. Nothing in the layout announces that a name has gone. 3. **Treat an empty selection as a stop condition, not a footnote.** What an aggregate over no rows gives you **varies by design** — an absent-value marker, an error, or zero for a total — so do not rely on a particular one of those to alert you. Check the row count you selected on, and decide what the report does when it is zero. 4. **Read the row count of a filtered selection as a count of measurements of that one measure**, which is the only reading of it that is defensible. ## The rule worth having as a team An aggregate over a value column with no condition on the name column is a defect, and it is cheap to spot in review because it is visible in the expression itself — there is no need to know the data to see that a quantity was never named. Two habits follow, and both are judgment calls a senior person owns rather than rules a tool can impose: - Every number that reaches a reader should be traceable to a measure name that was stated somewhere in producing it. - Any code path that treats the value column as one quantity should be rewritten even when its current output happens to look sensible, because it looks sensible only for as long as the mix of measures stays as it is today — and the mix is data, so it will not. ## The short answer The number is meaningless because the arrangement moved a measurement's identity out of the header and into a cell, and the aggregate never read that cell. The general form of the lesson: in this layout, no read of the value column is complete until it has said which measure it is about.

  • The report is corrected to average one measure at a time. What still needs care?
    That the name it selects on matches what the producer emits. A renamed measure, or one split into two names, quietly yields fewer rows and a mean that still looks plausible. Check how many rows the selection actually matched, and decide in advance what the report does when that count is zero rather than letting a downstream value stand in for it.
  • Does a per-subject average of the value column have the same problem?
    Yes, and one more on top. The unit problem is unchanged, and the result is also weighted by measurement count: a subject with ten measurements influences it ten times as much as one with a single measurement. Conditioning on the name column fixes both at once, because within one measure every subject contributes comparably.
  • Why does one column per measure not have this failure?
    Because each measure's numbers sit in a column of their own, so an aggregate names the quantity in the act of naming the column, and a column of mixed units cannot appear by accident. It pays for that elsewhere — a new measure is a change of schema — but the semantics sit where the aggregate can see them.

saying these in an interview costs you the question

  • Aggregates the value column without conditioning on the name column
  • Assumes a shared column implies a shared unit
  • Reads the table's row count as a count of subjects
  • Says the average is fine because the measures have similar scales
  • Blames the data volume rather than the arrangement's semantics
  • Thinks an empty selection will always announce itself