ScreenshotNeo

BlogHow-to

How to Find the Mean, Median, and Mode in Python

Learn how to calculate mean, median, and mode in Python with the statistics module, handle ties and empty data, and avoid common mistakes.

By the ScreenshotNeo team29 September 20268 min read

How to Find the Mean, Median, and Mode in Python

Python’s standard-library statistics module calculates the mean, median, and mode without requiring third-party packages. For ordinary numeric data, import the module and call statistics.mean(), statistics.median(), and statistics.mode().

import statistics

data = [2, 4, 4, 6, 8]

print("Mean:", statistics.mean(data))
print("Median:", statistics.median(data))
print("Mode:", statistics.mode(data))

This prints:

Mean: 4.8
Median: 4
Mode: 4

The mean is the arithmetic average, the median is the middle value after sorting, and the mode is the most frequently occurring value. The rest of this guide explains exactly how each function behaves, including even-sized datasets, tied modes, empty input, non-numeric values, precision, and production concerns.

Use Python’s statistics module

The module is included with Python, so installation is not required. You can use qualified names:

import statistics

values = [2, 4, 4, 6, 8]
mean_value = statistics.mean(values)
median_value = statistics.median(values)
mode_value = statistics.mode(values)

Or import the functions directly:

from statistics import mean, median, mode

values = [2, 4, 4, 6, 8]

print(mean(values))
print(median(values))
print(mode(values))

Qualified names such as statistics.mean make it clearer where each function comes from in larger programs. Direct imports are convenient in small scripts.

How the mean works

The mean adds every numeric observation and divides the total by the number of observations:

import statistics

scores = [70, 80, 90]
print(statistics.mean(scores))  # 80

The function accepts integer and floating-point values and returns the arithmetic average. A mean can be a value that never appears in the input. For example, the mean of [1, 2] is 1.5.

Use the mean when every value should contribute to the summary and extreme values are meaningful. A very large or very small observation can pull the mean toward itself, so the median may describe a skewed dataset better.

Mean with decimals and exact values

For normal measurements, floats are usually sufficient:

import statistics

prices = [19.99, 24.50, 31.25]
print(statistics.mean(prices))

If decimal rounding matters, use decimal.Decimal values rather than converting a rounded result after the calculation:

from decimal import Decimal
import statistics

prices = [Decimal("19.99"), Decimal("24.50"), Decimal("31.25")]
print(statistics.mean(prices))

How the median works

The median is the middle position after the values are ordered. Python’s median() handles both odd and even numbers of observations.

The median uses the middle position after ordering; even-sized data averages the two center values.
The median uses the middle position after ordering; even-sized data averages the two center values.

Odd number of values

import statistics

values = [9, 2, 7, 4, 5]
print(statistics.median(values))  # 5

After ordering, the data is [2, 4, 5, 7, 9], so 5 is the middle value. You do not need to sort the list yourself; median() performs the required ordering internally.

Even number of values

With an even number of observations, Python averages the two central values:

import statistics

values = [1, 3, 5, 7]
print(statistics.median(values))  # 4.0

The two central values are 3 and 5, and their average is 4.0. That result does not have to be an observed item.

For ordinal data where averaging is not meaningful, use median_low() or median_high():

import statistics

values = [1, 3, 5, 7]
print(statistics.median_low(values))   # 3
print(statistics.median_high(values))  # 5

median_low() selects the lower middle observation and median_high() selects the higher one. These are useful when the result must be one of the original values, such as a ranked category.

How the mode works

The mode is the value that occurs most often:

import statistics

votes = ["red", "blue", "red", "green", "red"]
print(statistics.mode(votes))  # red

Unlike mean and median, mode() also works with nominal, non-numeric values such as strings. It is appropriate for categories, labels, survey responses, and other values where arithmetic has no meaning.

Several tied modes

A dataset can have multiple values tied for the highest frequency. In Python 3.8 and later, mode() returns the first tied value encountered in the input:

import statistics

values = ["cat", "dog", "dog", "cat"]
print(statistics.mode(values))  # cat

Use multimode() when every tied mode matters:

import statistics

values = ["cat", "dog", "dog", "cat", "bird"]
print(statistics.multimode(values))  # ['cat', 'dog']

multimode() returns tied modes in order of first appearance. If you support Python versions older than 3.8, check that version’s documentation: older behavior for multiple modes differed.

Handling empty data safely

mean(), median(), and mode() raise statistics.StatisticsError when the input is empty. Check before calculating or catch the exception at a user-facing boundary.

import statistics

values = []

if not values:
    print("No data to summarize")
else:
    print("Mean:", statistics.mean(values))
    print("Median:", statistics.median(values))
    print("Mode:", statistics.mode(values))

For a reusable function, make the empty-data policy explicit:

import statistics


def summarize(values):
    if not values:
        return {"mean": None, "median": None, "mode": None}

    return {
        "mean": statistics.mean(values),
        "median": statistics.median(values),
        "mode": statistics.mode(values),
    }

print(summarize([2, 4, 4, 6, 8]))
print(summarize([]))

multimode([]) is different: it returns an empty list rather than raising StatisticsError.

Choosing the right statistic

Statistic Use it to answer Input Important behavior
Mean What is the arithmetic average? Numeric values Sensitive to extreme values
Median What is the middle position? Ordered numeric values Even counts average the two middle values
Mode Which value appears most often? Numeric or nominal values Returns one first-encountered winner on a tie
Multimode Which values share the highest frequency? Any hashable values Returns all tied modes

For a distribution with outliers, report both mean and median when readers need context. For categories, report the mode or all modes; a mean of category labels is not meaningful.

Complete example with validation

The following script validates that input exists, calculates all three measures, and reports tied modes:

import statistics


def describe(values):
    if not values:
        raise ValueError("values must contain at least one item")

    return {
        "count": len(values),
        "mean": statistics.mean(values),
        "median": statistics.median(values),
        "mode": statistics.mode(values),
        "all_modes": statistics.multimode(values),
    }

numbers = [2, 4, 4, 6, 8]
summary = describe(numbers)

for name, value in summary.items():
    print(f"{name}: {value}")

Keep validation near the boundary where data enters your program. That makes empty lists, malformed records, and unexpected types easier to diagnose than allowing an exception deep inside a reporting step.

Performance, reliability, and data preparation

For small and medium in-memory lists, the standard-library functions are usually the simplest reliable choice. Median calculation requires ordering the observations, so it generally costs more than a single pass through the data. If your input is very large, avoid repeatedly calculating a median inside a loop; collect the required values and calculate once, or use a data-processing system designed for streaming quantiles.

Do not silently coerce bad input. Strings such as "10" are not numeric observations for mean() or median(). Convert and validate deliberately:

raw = ["10", "20", "30"]
values = [float(item) for item in raw]

For reproducible reports, record the number of observations and the filtering rules alongside the result. A mean calculated after dropping missing values answers a different question from a mean calculated after treating missing values as zero.

Troubleshooting common errors

StatisticsError: mean requires at least one data point

Cause: The iterable is empty.

Fix: Check if values before calling the function, or catch statistics.StatisticsError and return a clear validation message.

StatisticsError: no unique mode

Cause: This can occur on older Python versions when multiple values tie.

Fix: Use statistics.multimode() when all winners are needed, or use Python 3.8+ behavior where mode() returns the first encountered winner.

TypeError while calculating mean or median

Cause: The data contains incompatible types, such as strings mixed with numbers.

Fix: Normalize values before calculation and reject records that cannot be converted safely.

The median is a decimal that was not in the list

Cause: The input has an even number of observations, so Python averages the two central values.

Fix: Use median_low() or median_high() when the result must be an observed item.

The mode is not the value you expected

Cause: There is a tie, and mode() selects the first tied value encountered.

Fix: Inspect statistics.multimode(values) and decide whether your application needs a tie-breaking rule.

Or skip the browser setup

If your Python workflow also needs screenshots of charts, reports, or source pages, ScreenshotNeo provides a single website screenshot API request. It accepts the consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and whether the shot was billed.

See the ScreenshotNeo documentation for the complete API reference. This is a direct call; no browser automation setup is required.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests

r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also supports full-page captures with lazy images loaded, CSS element capture, dark mode, device presets, custom viewports, retina scale, PDFs, custom CSS and JavaScript, clicks, selector waits, delays, network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous jobs, signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Existing parameter names used by other screenshot APIs work as well, which can reduce migration changes.

An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots. Only clean shots are billed, so failed captures do not consume paid usage.

Sign up for the free ScreenshotNeo plan to get 1,000 screenshots each month with no card.

Frequently asked questions

Do I need to install a package?

No. statistics is part of Python’s standard library.

Can mode process strings?

Yes. Mode is the one measure in this module intended for nominal, non-numeric data as well as numbers.

Should I sort the list before calling median?

No. median() performs the ordering needed for its calculation. Sorting yourself is only useful if you also need the ordered data.

How do I get every mode?

Call statistics.multimode(values). It returns all values tied for the highest frequency.

What should an API return for an empty dataset?

Choose a documented policy, such as a validation error or null fields. Do not treat missing data as zero unless that is the intended meaning.

Where is the official reference?

See the Python statistics library documentation for current function signatures, supported types, exceptions, and version notes. The API’s original design is documented in PEP 450.