Skip to content

03-01: Mean, Median and Mode

A measure of central tendency answers "what is a typical value?" with a single number. There are four in common use, and choosing the wrong one is one of the easiest ways to mislead with a correct calculation.


The Arithmetic Mean

The sum of the values divided by how many there are.

Population mean     μ  =  Σ X  /  N
Sample mean         x̄  =  Σ x  /  n

Properties that matter later:

  1. The mean uses every value, so it is sensitive to extremes.
  2. The deviations from the mean always sum to zero: Σ(x − x̄) = 0. This is why the variance squares them (04-01).
  3. The mean minimizes Σ(x − c)² over all choices of c — it is the least-squares centre, the idea behind regression (13-02).
  4. is an unbiased estimator of μ — the foundation of Chapters 08–11.

The Median

The middle value when the data is sorted.

Sort the data, then:
  n odd   →  median = the value at position (n + 1) / 2
  n even  →  median = average of the values at positions n/2 and n/2 + 1

The median is a resistant (robust) measure: changing the largest value to any larger number does not move it at all.


The Mode

The value that occurs most often.

  • No mode — every value occurs once.
  • Unimodal — one value dominates.
  • Bimodal — two values tie for most frequent (often a sign of two mixed subgroups).
  • Multimodal — three or more.

The mode is the only centre available for nominal data (01-01).


The Midrange

Midrange  =  (minimum + maximum) / 2

Quick, but built from exactly the two most extreme values, so it is the least stable of the four. Useful as a rough check, never as the headline number.


Choosing the Right Measure

Situation Use Why
Roughly symmetric, no outliers Mean Uses all the data; feeds into every later test
Skewed, or outliers present Median Resistant to the long tail
Nominal / categorical data Mode The only one defined
Ordinal data Median or mode Order exists, spacing does not
Reporting "typical income", "typical house price" Median Income distributions are strongly right-skewed
Quick range check Midrange Fast, crude

Mean vs. median as a skewness diagnostic:

mean ≈ median        →  roughly symmetric
mean >  median       →  right-skewed  (long tail pulls the mean up)
mean <  median       →  left-skewed   (long tail pulls the mean down)

Pearson's coefficient of skewness turns that comparison into a number:

SK  =  3 (x̄ − median) / s

|SK| < 1      →  approximately symmetric
SK ≥ 1        →  substantially right-skewed
SK ≤ −1       →  substantially left-skewed

Worked Example

Nine annual salaries in a small firm (thousands of dollars):

38  42  42  45  48  52  55  60  248
n = 9,  sorted already,  Σx = 630

Mean      x̄ = 630 / 9 = 70.0
Median      = value at position (9+1)/2 = 5th = 48.0
Mode        = 42  (appears twice; all others once)
Midrange    = (38 + 248) / 2 = 143.0

Interpretation. The mean of 70 describes nobody: eight of the nine people earn less than it. One founder's salary of 248 drags it up. The median of 48 is the honest "typical salary". Mean (70) > median (48) confirms a strong right skew — exactly the pattern income data always shows.

Remove the 248 and recompute:

n = 8,  Σx = 382
Mean   = 47.75          (dropped 22.25)
Median = (45 + 48)/2 = 46.5   (dropped 1.5)

That contrast — the mean moves 15× further than the median — is the definition of resistance.


Excel

' ── The four measures ───────────────────────────────────────────────
=AVERAGE(A2:A10)            ' mean            -> 70
=MEDIAN(A2:A10)             ' median          -> 48
=MODE.SNGL(A2:A10)          ' single mode     -> 42
=MODE.MULT(A2:A10)          ' ALL modes (spills; use for bimodal data)
=(MIN(A2:A10)+MAX(A2:A10))/2   ' midrange     -> 143

' ── Guards and variants ─────────────────────────────────────────────
=AVERAGEIF(B2:B10, "Biology", A2:A10)      ' mean of one subgroup
=AVERAGEIFS(A2:A10, B2:B10,"Biology", C2:C10,">=70")
=AVERAGEA(A2:A10)           ' counts text as 0 — usually NOT what you want
=TRIMMEAN(A2:A10, 0.2)      ' drops top & bottom 10% — a robust mean
=COUNT(A2:A10)              ' n, numeric cells only

' ── Skewness check ──────────────────────────────────────────────────
=3*(AVERAGE(A2:A10)-MEDIAN(A2:A10))/STDEV.S(A2:A10)   ' Pearson's SK
=SKEW(A2:A10)               ' Excel's own (adjusted Fisher-Pearson) skewness

Note

AVERAGE ignores text and blank cells; AVERAGEA treats text as 0 and TRUE as 1. If your mean looks too low, check whether a number is stored as text (01-02).

Analysis ToolPak: Data ▸ Data Analysis ▸ Descriptive Statistics → tick Summary statistics to get mean, median, mode, standard deviation, skewness, kurtosis, range, min, max, sum, and count in one table.


R

salary <- c(38, 42, 42, 45, 48, 52, 55, 60, 248)

mean(salary)        # 70
median(salary)      # 48
range(salary)       # 38 248
mean(range(salary)) # midrange -> 143

# R has no built-in mode() for statistics (mode() reports storage type),
# so define one:
stat_mode <- function(x) {
  tab <- table(x)
  as.numeric(names(tab)[tab == max(tab)])      # returns ALL modes
}
stat_mode(salary)   # 42

# Robust variants
mean(salary, trim = 0.1)     # 10% trimmed mean from each end
mean(salary, na.rm = TRUE)   # ignore missing values

# Everything at once
summary(salary)
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
#   38.00   42.00   48.00   70.00   55.00  248.00

library(psych)
describe(salary)    # n, mean, sd, median, trimmed, mad, min, max, skew, kurtosis

# Skewness diagnostics
3 * (mean(salary) - median(salary)) / sd(salary)   # Pearson's SK -> 0.98
psych::skew(salary)

# By group
tapply(df$score, df$group, mean)
aggregate(score ~ group, data = df, FUN = median)

Python

import numpy as np
import pandas as pd
from scipy import stats

salary = pd.Series([38, 42, 42, 45, 48, 52, 55, 60, 248])

salary.mean()          # 70.0
salary.median()        # 48.0
salary.mode()          # 0    42   (a Series — handles multimodal data)
(salary.min() + salary.max()) / 2      # midrange -> 143.0

# Robust variants
stats.trim_mean(salary, 0.1)           # 10% trimmed mean
salary.mean(skipna=True)               # missing values ignored by default

# Everything at once
salary.describe()
# count      9.000000
# mean      70.000000
# std       67.113709
# min       38.000000
# 25%       42.000000
# 50%       48.000000
# 75%       55.000000
# max      248.000000

# Skewness diagnostics
3 * (salary.mean() - salary.median()) / salary.std()   # Pearson's SK
salary.skew()                                          # adjusted Fisher-Pearson

# By group
df.groupby("major")["score"].mean()
df.groupby("major")["score"].agg(["mean", "median", "count"])

Quick Reference

Measure Formula Excel R Python
Mean Σx / n AVERAGE mean(x) s.mean()
Median middle of sorted data MEDIAN median(x) s.median()
Mode most frequent MODE.SNGL / MODE.MULT custom (table) s.mode()
Midrange (min + max)/2 (MIN+MAX)/2 mean(range(x)) (s.min()+s.max())/2
Trimmed mean mean after dropping tails TRIMMEAN mean(x, trim=) stats.trim_mean
Conditional mean mean of a subgroup AVERAGEIFS tapply / aggregate groupby().mean()
Skewness 3(x̄ − med)/s SKEW psych::skew s.skew()
Full summary ToolPak ▸ Descriptive Statistics summary() / describe() s.describe()

Common Mistakes

  • Reporting the mean of strongly skewed data (salary, house price, waiting time) as "typical".
  • Assuming there is always exactly one mode — MODE.SNGL returns only the first, hiding bimodality.
  • Forgetting to sort before finding a median by hand.
  • Averaging averages: the mean of three class averages is not the overall mean unless the classes are the same size — that is what the weighted mean in 03-02 is for.
  • Letting blank cells count as zeros (AVERAGEA, or filling blanks with 0).

Exercises: 03-01: Exercises — Mean, Median and Mode


⬅️ Previous: 02-02: Graphical Displays ➡️ Next: 03-02: Weighted and Grouped Means