Python Statistics with Python

Summarise data with Python's statistics module: centre, spread and percentiles, the effect of outliers and how to report results honestly.

Lesson 79 of 107Advanced13 min read

Descriptive statistics summarise a set of numbers: where the values are centred (mean, median, mode), how spread out they are (range, variance, standard deviation), and how they are distributed (percentiles). Python's built-in statistics module calculates all of these without installing anything:

Python
from statistics import mean, median, stdev
minutes = [10, 12, 14, 16, 48]
print(mean(minutes), median(minutes), round(stdev(minutes), 2))   # 20 14 15.81

The numbers are the easy part. This lesson also covers choosing the right summary, the difference between sample and population formulas, how the way data was collected limits what it can tell you, and how to report statistics so readers don't draw the wrong conclusion. The examples analyse how long repairs take at a bicycle workshop.

Location summaries

The three common measures of centre answer slightly different questions:

MeasureFunctionMeaningFor [10, 12, 14, 16, 48]
meanmean()sum divided by count20
medianmedian()middle value when sorted14
modemode() / multimode()most frequent valueevery value once

The mean uses every value, so one unusual observation pulls it strongly: the 48-minute repair lifts the mean to 20 even though four of five repairs took 16 minutes or less. The median only cares about the middle position, so it barely moves. When data is skewed, as durations, prices and incomes often are, the median usually describes a "typical" case better, and reporting both reveals the skew.

With an even number of values, median() averages the two middle ones; median_low() and median_high() return an actual data value instead. mode() suits categories such as the most common repair type; multimode() returns every value tied for most frequent.

Variation

Spread tells you how consistent the values are. Two workshops can both average 20 minutes, one with every repair between 18 and 22, the other ranging from 5 to 60.

  • Range: max(x) - min(x); simple, but decided entirely by the two extremes.
  • Variance: the average squared distance from the mean.
  • Standard deviation: the square root of the variance, in the same units as the data (minutes), so it's easier to interpret.
Python
from statistics import stdev, pstdev, variance
minutes = [10, 12, 14, 16, 48]
print(round(stdev(minutes), 2), round(pstdev(minutes), 2))   # 15.81 14.14

stdev() and variance() are sample statistics: they divide by n − 1, which corrects for estimating the spread of a larger process from a sample. pstdev() and pvariance() are population statistics: they divide by n, appropriate when you have every value of interest. With these five repairs as a sample of all repairs, stdev() is the right choice. The difference shrinks as n grows, but matters for small datasets.

Sampling

Every statistic describes the data you have, which may not represent what you want to know about. Ask how the observations were collected:

  • Were repairs timed only on quiet weekday mornings? Then weekend rush times are missing.
  • Did mechanics only record repairs that went smoothly? Then difficult jobs are under-represented.
  • Are five repairs enough to say anything general at all?

Data collected because it was convenient can differ systematically from the whole process, and no formula corrects that. Larger samples reduce random noise but not systematic bias.

Write down the selection: the period, which repairs were included or excluded, and how many observations there are. A statistic quoted without its sample size and collection method is hard for anyone to judge. When the question needs a fair sample, choose observations randomly, for example with random.sample(all_job_ids, 30), rather than taking whichever were easiest to record.

Interpretation

A number on its own isn't a finding. Report statistics with:

  • units: "median repair time 14 minutes", not "median 14";
  • the count: "n = 5 repairs";
  • centre and spread together: "median 14 min, ranging from 10 to 48";
  • known limitations: "one repair needed a part ordered in; it accounts for the 48".
Python
from statistics import median, quantiles
minutes = [10, 12, 14, 16, 48, 11, 13, 15, 17, 19]
q1, q2, q3 = quantiles(minutes, n=4)
print(f"n={len(minutes)}, median {median(minutes)} min, middle half {q1}-{q3} min")

Be careful with relationships. If repairs on older bikes take longer, the data shows an association; it doesn't prove that age causes the delay. Older bikes might simply be booked for bigger jobs. statistics.correlation() (Python 3.10+) measures how closely two variables move together, but deciding why needs knowledge of the process, not just the numbers.

Independent practice and a worked check

Task: summarise repair durations with units, sample size, location and spread, explaining an unusually long observation.

Python
from statistics import mean, median, stdev

minutes = [22, 18, 25, 20, 19, 75, 21]
note = "The 75-minute repair waited for a replacement derailleur."

print(f"n = {len(minutes)} repairs")
print(f"median {median(minutes)} min, mean {mean(minutes):.1f} min")
print(f"sample sd {stdev(minutes):.1f} min, range {min(minutes)}-{max(minutes)} min")
without = [m for m in minutes if m != 75]
print(f"without the outlier: median {median(without)} min, mean {mean(without):.1f} min")
print(note)

The median moves from 21 to 20.5 minutes when the outlier is set aside, while the mean drops from 28.6 to 20.8, showing which summary is robust. The outlier is reported and explained, not silently deleted. For the worked check, the statistic generally less affected by one extreme duration is the median.

Reference and next practice

The statistics module documentation lists every function with examples. Continue with data visualization and charts and distributions and percentiles. Practise with the Python exercises and Python quiz.

Statistics with Python Summary

  • Location summaries: Mean summarizes the arithmetic average while median identifies the middle sorted value.
  • Variation: Variance and standard deviation summarize spread using squared deviations.
  • Sampling: A collected sample may differ from the full process being studied.
  • Interpretation: A numerical summary needs units, context and an explanation of its limitations.

Statistics with Python Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Statistics with Python in a small program

Python
from statistics import mean, median, stdev
minutes = [10, 12, 14, 16, 48]
print(mean(minutes))
print(median(minutes))
print(round(stdev(minutes), 2))
Output
20
14
15.81
Line-by-line explanation
  1. Line 3The mean, 100 / 5, is pulled up by the 48-minute repair.
  2. Line 4The median is the middle sorted value, 14, unaffected by how large the outlier is.
  3. Line 5The sample standard deviation, rounded to two decimal places.
Example 2

A complete repair-time summary

Python
from statistics import mean, median, stdev, multimode

repairs = {
    "puncture": [10, 12, 9, 11, 14],
    "brakes": [25, 30, 28, 26, 61],
    "gears": [35, 40, 38, 42, 36],
}
all_minutes = [m for times in repairs.values() for m in times]
print(f"All repairs: n={len(all_minutes)}, mean {mean(all_minutes):.1f}, median {median(all_minutes)} min")

for kind, times in repairs.items():
    spread = stdev(times)
    print(f"{kind:<9} n={len(times)} median {median(times):>4} min  sd {spread:5.1f}  range {min(times)}-{max(times)}")

outliers = {kind: [m for m in times if m > 2 * median(times)] for kind, times in repairs.items()}
print("Longer than twice their type's median:", {k: v for k, v in outliers.items() if v})
print("Most common durations:", multimode(all_minutes))
Output
All repairs: n=15, mean 27.8, median 28 min
puncture  n=5 median   11 min  sd   1.9  range 9-14
brakes    n=5 median   28 min  sd  15.2  range 25-61
gears     n=5 median   38 min  sd   2.9  range 35-42
Longer than twice their type's median: {'brakes': [61]}
Most common durations: [10, 12, 9, 11, 14, 25, 30, 28, 26, 61, 35, 40, 38, 42, 36]
Line-by-line explanation
  1. Lines 11 to 13Summaries per repair type reveal that only brakes vary a lot.
  2. Lines 15 to 16A simple screening rule flags repairs over twice the median for their type; 61 minutes stands out among brake jobs. Flagged values are for investigating, not deleting.
  3. Line 17Every value appears once, so multimode() returns them all: there is no meaningful mode here.

Common Statistics with Python Mistakes

Reporting only the mean of skewed data

Don't
print(f"Repairs take {mean(minutes)} minutes")          # 20: no repair took close to 20
Do
print(f"Median {median(minutes)} min (n={len(minutes)}); mean {mean(minutes)} min "
      f"raised by one {max(minutes)}-minute repair")

Using the population formula for a sample

Don't
spread = pstdev(sample_of_repairs)    # underestimates the spread of all repairs
Do
spread = stdev(sample_of_repairs)     # n - 1 denominator for a sample

Statistics with Python in Real Projects

Statistics in everyday decisions

Service teams quote median response times because a few extreme tickets would distort the mean. Web performance is reported as percentiles, such as "95th percentile page load 1.8 s", because averages hide the slowest experiences. Quality control watches standard deviation: a production line whose average is perfect but whose spread is growing is about to produce faulty parts.

For larger datasets, pandas offers describe(), median(), quantile() and std() on whole columns, and NumPy and SciPy add more advanced statistics. The judgement about what to measure, from which sample, and how to report it stays the same.

Statistics with Python FAQ

What is the difference between mean and median?

The mean adds all values and divides by the count, so extreme values pull it. The median is the middle value when sorted, so it's resistant to outliers. For skewed data such as times, prices or incomes, the median usually represents a typical value better.

What is the difference between stdev and pstdev in Python?

stdev() is the sample standard deviation, dividing by n − 1; use it when your data is a sample of a larger process. pstdev() is the population standard deviation, dividing by n; use it when you have every value of interest.

Do I need NumPy for statistics in Python?

Not for basic descriptive statistics: the built-in statistics module covers mean, median, mode, variance, standard deviation, quantiles and correlation. NumPy and pandas are faster for large datasets and many columns.

How do I find outliers in Python?

A common rule flags values more than 1.5 times the interquartile range beyond the first or third quartile, computed with statistics.quantiles(data, n=4). Treat flagged values as questions to investigate, not automatic deletions.

Why does mode() return the first value when nothing repeats?

Since Python 3.8, mode() returns the first of several equally common values instead of raising an error. Use multimode() to see every tied value, which shows when there's no single meaningful mode.

Statistics with Python Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Multiple choiceeasy

Which statistic is generally less affected by one extreme duration?

Multiple choicemedium

Which review concern is valid for statistics with python?

Statistics with Python Quiz

2 questions to check what you learned.

  1. Which statistic is generally less affected by one extreme duration?

    • Mean
    • Median
    • Python ignores the distinction
  2. Which statement correctly describes sampling?

    • A collected sample may differ from the full process being studied.
    • Only the example output matters, not the rule
    • Every operation has the same behavior