Statistics Z-test and T-test

Z-tests and t-tests both check whether a sample mean differs from a claimed value, but the right one to use depends on whether you know the population's standard deviation and how large your sample is.

The Common Question Both Tests Answer

Z-tests and t-tests both help answer the same basic question: is a sample mean far enough from some claimed or expected value that it probably isn't just random sampling noise? They compute a similar kind of statistic - the gap between the sample mean and the hypothesized value, measured in standard-error units - but they differ in what they assume you know about the population.

When to Use a Z-test

  • You know the true population standard deviation (sigma) from historical or theoretical sources
  • The sample size is reasonably large so the sampling distribution of the mean is close to normal
  • The population itself is roughly normal, or the sample is large enough for the Central Limit Theorem to kick in

Example

import math

def z_test_statistic(sample_mean, pop_mean, pop_std, n):
    se = pop_std / math.sqrt(n)
    return (sample_mean - pop_mean) / se

# Known population std dev (sigma) from historical data = 15
z = z_test_statistic(sample_mean=104, pop_mean=100, pop_std=15, n=40)
print("z =", round(z, 3))

When to Use a T-test

In most real situations you don't actually know the population's true standard deviation - you only have your sample. The t-test handles that uncertainty by estimating the standard deviation from the sample itself and comparing the resulting statistic to the t-distribution instead of the normal distribution. The t-distribution has heavier tails than the normal curve, which builds in some extra caution for the added uncertainty, especially with a small sample. Its exact shape depends on the degrees of freedom, usually n - 1.

Example

import math

def sample_std(data):
    mean = sum(data) / len(data)
    variance = sum((x - mean) ** 2 for x in data) / (len(data) - 1)
    return math.sqrt(variance)

def t_test_statistic(sample, pop_mean):
    n = len(sample)
    mean = sum(sample) / n
    s = sample_std(sample)
    se = s / math.sqrt(n)
    return (mean - pop_mean) / se, n - 1

scores = [88, 92, 79, 95, 84, 90, 76, 88, 91]
t_value, df = t_test_statistic(scores, pop_mean=85)
print("t =", round(t_value, 3), " df =", df)
AspectZ-testT-test
Population std dev (sigma)KnownUnknown (estimated from the sample)
Typical sample sizeAny size, often large (n >= 30)Often small (n < 30), but valid at any size
Reference distributionStandard normal (Z)t-distribution with n - 1 degrees of freedom
Tail thicknessFixedHeavier tails, closer to normal as n grows
Note: As the sample size grows, the t-distribution gets closer and closer to the normal distribution, so for large samples (say, several hundred observations) a t-test and a z-test will give you nearly identical results.
  1. Ask: do I know the true population standard deviation from an independent source?
  2. If yes, use a z-test with the normal distribution
  3. If no, estimate the standard deviation from your sample and use a t-test with n - 1 degrees of freedom
  4. If your sample is very large, the t-test and z-test will give nearly identical results anyway
Note: Don't switch to a z-test just because your sample happens to be large if you're still estimating the standard deviation from that same sample - you're substituting an estimate for a genuinely known population value. When the true population standard deviation isn't known from an independent source, the t-test is the safer default.