Table of Contents
A Z-test checks whether a sample mean is significantly different from a claimed population mean but it only works under one specific condition that trips up more dissertation students than any other part of the test: you have to actually know the population standard deviation, not estimate it from your own data. It covers the one-sample and two-sample Z-test in R, both the packaged function and the manual calculation, and more importantly how to tell whether a Z-test is even the right test for what you're doing.
What Is a Z-Test and When Does It Apply
Z-test definition: testing a population mean when σ is known
A Z-test checks whether a sample mean is significantly different from a stated population mean, using the standard normal distribution to calculate the test statistic and p-value. It's typically used when the population standard deviation is known and the sample size is sufficiently large (usually n ≥ 30). The test statistic follows the familiar form:
Z = (x̄ - μ) / (σ / √n)
where x̄ is your sample mean, μ is the hypothesized population mean, σ is the known population standard deviation, and n is your sample size. That last requirement — a known σ — is the whole test, and it's also the reason most dissertation datasets can't legitimately use one. More on that below.
Z-test vs. Z-score: two different tools with a confusingly similar name
If you've already read our guide on calculating Z-scores in R, don't confuse the two. A Z-score standardizes a single data point — it tells you how many standard deviations that point sits from the mean. A Z-test is a hypothesis test — it tells you whether an entire sample's mean is statistically different from a claimed population value. A Z-score is descriptive; a Z-test produces a decision (reject or fail to reject a null hypothesis). You'll often calculate a Z-score as an intermediate step inside a Z-test, but they answer different questions.
The n ≥ 30 and known-σ conditions — and why most dissertation data fails them
If the population standard deviation is unknown, a Z-test is typically not appropriate, though when the sample size is large, the sample standard deviation can be used as an estimate and the Z-test can provide approximate results. In practice, analysts rarely use Z-tests because it's rare that they'll know the population standard deviation and this is the detail that trips up most students.
If you're working with survey data, experimental results, or any dataset where σ was estimated from your own sample rather than supplied by an external, established source, you're very likely looking at a t-test, not a Z-test, regardless of your sample size. You'll also want your data to be reasonably close to normally distributed see our guide on testing normality with the Shapiro-Wilk test if you're not sure.
If you're not sure whether your data qualifies for a Z-test or you need to justify the choice in a methodology chapter, that's exactly the kind of question worth getting a second opinion on before you run the analysis, message us on WhatsApp and we'll help you check.
One-Sample Z-Test in R Using BSDA::z.test()
Installing and loading the BSDA package
Base R doesn't ship a dedicated Z-test function — t.test() exists, but there's no built-in z.test(). The BSDA package (Basic Statistics and Data Analysis) fills that gap and is the function every top-ranking Z-test tutorial actually uses, so it's worth installing once and keeping.
install.packages("BSDA")
library(BSDA)
Worked example with real computed output
We'll test a claim against R's built-in mtcars dataset: suppose a manufacturer claims their vehicle class averages 21 mpg, and historical testing has established the population standard deviation at 6 mpg. Does our sample of 32 cars support or contradict that claim?
z.test(x = mtcars$mpg, mu = 21, sigma.x = 6)
| Output element | Value |
|---|---|
| Sample mean (x̄) | 20.09 |
| Z statistic | -0.8574 |
| p-value (two-sided) | 0.3912 |
| 95% confidence interval | [18.01, 22.17] |
| Alternative hypothesis | true mean ≠ 21 |
Reading the output: test statistic, p-value, confidence interval
At α = 0.05, p = 0.3912 is well above the threshold, we fail to reject the null hypothesis. The sample doesn't provide enough evidence to say the true population mean differs from 21 mpg. Notice the 95% confidence interval [18.01, 22.17] contains 21, that's not a coincidence. Whenever your hypothesized value falls inside the confidence interval, the two-sided test will fail to reject at the matching alpha level. It is a useful cross-check: if your p-value and your CI ever seem to disagree, one of them was calculated wrong. If you're unsure how to read a p-value in context, see our guide to interpreting p-values.
Note: this example assumes σ = 6 is genuinely known from an external source, not estimated from the sample itself, see the last section of this guide for why that assumption matters more than most students realize.
Manual Calculation Path (pnorm/qnorm)
The Z-formula and what each term means
z.test() is convenient, but knowing what it's doing under the hood matters — most methodology chapters expect you to show the calculation, not just the function call. The formula is:
Z = (x̄ - μ) / (σ / √n)
x̄ is your observed sample mean, μ is the value you're testing against, σ is the known population standard deviation, and n is your sample size. Dividing σ by √n gives you the standard error — how much sample means are expected to vary just from sampling noise. The Z-statistic tells you how many standard errors your observed mean sits from the hypothesized value.
Computing the test statistic and p-value by hand in R
Using the same mtcars$mpg example from the previous section, testing a claimed mean of 21 mpg against a known σ of 6:
xbar <- mean(mtcars$mpg)
mu <- 21
sigma <- 6
n <- length(mtcars$mpg)
Z <- (xbar - mu) / (sigma / sqrt(n))
Z
p_value <- 2 * (1 - pnorm(abs(Z)))
p_value
| Quantity | Value |
|---|---|
| Z | -0.8574 |
| Two-sided p-value | 0.3912 |
These match the z.test() output from the previous section exactly — the function isn't doing anything more sophisticated than this formula plus a lookup against the normal distribution.
Two-tailed vs. one-tailed p-value logic
The direction of your alternative hypothesis changes how you read pnorm(), not the Z-statistic itself:
# Left-tailed: H1: mu < 21
p_left <- pnorm(Z)
# Right-tailed: H1: mu > 21
p_right <- 1 - pnorm(Z)
# Two-tailed: H1: mu != 21
p_two <- 2 * (1 - pnorm(abs(Z)))
| Test direction | p-value |
|---|---|
| Left-tailed (μ < 21) | 0.1956 |
| Right-tailed (μ > 21) | 0.8044 |
| Two-tailed (μ ≠ 21) | 0.3912 |
Notice the left- and right-tailed p-values sum to 1, that's expected, since together they cover the entire distribution. The two-tailed p-value is double whichever one-tailed value corresponds to the direction your Z-statistic actually points. Get this backwards, doubling the wrong tail, and you'll report a p-value that's the complement of the correct one, which is a common error when students copy a formula without checking which side of zero their Z-statistic landed on.
Critical Value Approach as an Alternative to P-Values
Finding critical Z-values with qnorm()
The p-value approach asks "how likely is a result this extreme?" The critical value approach flips the question: "beyond what Z-value would I reject the null hypothesis?" Both methods use the same underlying distribution and always agree, but some instructors and journals still expect the critical value framing, so it's worth knowing.
# Two-tailed critical value at alpha = 0.05
z_crit_two <- qnorm(0.975)
z_crit_two
# Right-tailed critical value at alpha = 0.05
z_crit_right <- qnorm(0.95)
z_crit_right
| Test type (α = 0.05) | Critical Z-value |
|---|---|
| Two-tailed | ±1.96 |
| Right-tailed | +1.645 |
| Left-tailed | -1.645 |
Two-tailed vs. right-tailed vs. left-tailed rejection regions
The rejection region is the range of Z-values extreme enough to reject H₀:
| Alternative hypothesis | Reject H₀ when |
|---|---|
| μ ≠ value (two-tailed) | Z < -1.96 or Z > +1.96 |
| μ > value (right-tailed) | Z > +1.645 |
| μ < value (left-tailed) | Z < -1.645 |
A two-tailed test splits α across both tails (0.025 each), which is why its critical value is larger in magnitude than a one-tailed test's — you need a more extreme result to earn the same significance level when you're watching both directions at once.
Confirming p-value and critical-value approaches agree
Back to the running example: Z = -0.8574 for our test of mtcars mpg against a claimed mean of 21. For the two-tailed test at α = 0.05, the rejection region is Z < -1.96 or Z > +1.96. Since -0.8574 falls between those bounds, we fail to reject H₀ — the same conclusion the p-value (0.3912 > 0.05) gave us. This will always be true: the critical value method and the p-value method are two views of the same calculation, and if they ever disagree, one of them was computed incorrectly.
Two-Sample Z-Test in R
When to compare two population means with known σ
A two-sample Z-test asks whether two independent groups have different population means, the same logic as the one-sample test, extended to a comparison. It requires the same conditions as before, doubled: both population standard deviations must be known, and both samples should be reasonably large (guidelines vary, but at least 15 observations per group is a common threshold). This is the section most competing Z-test guides skip entirely, even though it's a natural next question once you've covered the one-sample case.
Worked example with BSDA::z.test() for two samples
Using mtcars again — this time comparing fuel economy between automatic and manual transmission cars, with population standard deviations assumed known at 6 mpg for each group (illustrative, matching the convention used earlier in this guide — see the note at the end of this section on why that assumption rarely holds in real research data):
auto <- mtcars$mpg[mtcars$am == 0]
manual <- mtcars$mpg[mtcars$am == 1]
z.test(x = auto, y = manual, sigma.x = 6, sigma.y = 6, mu = 0)
| Output element | Value |
|---|---|
| Mean, automatic (n=19) | 17.15 |
| Mean, manual (n=13) | 24.39 |
| Difference (auto − manual) | -7.24 |
| Z statistic | -3.3547 |
| p-value (two-sided) | 0.0008 |
| 95% CI on the difference | [-11.48, -3.01] |
Interpreting a non-significant result — and this one, which isn't
Unlike the one-sample example earlier in this guide, this result is significant: p = 0.0008 is well below 0.05, and the confidence interval [-11.48, -3.01] doesn't contain zero — both point to the same conclusion, that manual transmission cars in this sample average meaningfully higher mpg than automatics. That's worth contrasting directly with the one-sample section: a non-significant result (like Z = -0.86, p = 0.39 earlier) doesn't mean "no effect exists," it means the sample didn't provide enough evidence to detect one. A significant result like this one is more straightforward to interpret, but still describes this sample's comparison, not a universal claim about transmission types.
Warning!
This example assumes both population standard deviations are known — a convenience for teaching, not something you're likely to have with real dissertation data. If your σ values are estimated from your own samples (the overwhelmingly common case), you need a two-sample t-test, not a Z-test. The next section covers exactly this decision.
Z-Test vs. T-Test: Choosing the Right Test for Your Data
Decision table: known vs. unknown σ, sample size thresholds
| Condition | Use Z-test | Use t-test |
|---|---|---|
| Population σ | Known from an external, established source | Unknown — estimated from your sample |
| Sample size | Large (n ≥ 30 is the common rule of thumb) | Any size, but especially small samples |
| Test statistic distribution | Standard normal (Z) | t-distribution (accounts for extra uncertainty from estimating σ) |
| Typical dissertation use case | Rare — usually only when comparing against a documented population parameter | Common — almost all primary survey and experimental data |
As sample size grows large, the t-distribution converges toward the normal distribution, so the practical difference between the two tests shrinks — but the underlying assumption about σ doesn't change just because your n is big. That assumption, not the sample size, is what actually determines which test is defensible. If your data doesn't meet the normality assumption either test relies on, see our guide on hypothesis testing step by step for alternatives.
Common misuse: assuming σ known when it's actually estimated
The single most frequent error we see in dissertation methodology chapters is a Z-test run with a population standard deviation that was, in fact, calculated from the researcher's own sample data — R won't stop you from doing this, since z.test() will happily accept any number you feed it as sigma.x. But statistically, feeding in a sample-derived value defeats the purpose of the test: you're borrowing the certainty of a "known" σ you don't actually have. If you calculated your standard deviation with sd() on your own data, that's a sample estimate — switch to t.test() instead. The only legitimate known-σ scenarios in most research are cases like standardized test instruments with a published, historically established standard deviation, or process-control settings where σ has been established from decades of prior data — not your current dataset.
What to report in your methodology chapter
At minimum, report: the test statistic (Z), the p-value, the significance level used, the sample size, and — critically — a stated justification for why σ was treated as known. That last part is what committee members actually push back on, more often than the statistics themselves. The Wald test is a useful related read if your model involves estimated coefficients rather than a single mean.
Info!
Getting the test statistic and p-value from R is the easy part. Writing the APA-style justification for why a Z-test (rather than a t-test) was the correct choice for your specific data — and defending it if a committee member questions the known-σ assumption — is where most students get stuck. If you want a second opinion on your test choice or help drafting that section, message us on WhatsApp and we'll walk through your data with you.
Frequently Asked Questions
What is a Z-test used for in R?
A Z-test in R is used to test whether a sample mean is significantly different from a claimed population mean, when the population standard deviation is known. It's most commonly run with the z.test() function from the BSDA package.
How do I perform a Z-test in R?
Install and load the BSDA package, then call z.test(x = your_data, mu = hypothesized_mean, sigma.x = known_population_sd). The output gives you the Z statistic, p-value, and confidence interval.
Does R have a built-in Z-test function?
No. Base R includes t.test() but has no dedicated z-test function. The z.test() function comes from the BSDA package, which you need to install separately with install.packages("BSDA"). If you'd rather not add a package, the "Manual Calculation Path" section of this guide shows the equivalent pnorm()/qnorm() approach using only base R.
What is the difference between a Z-test and a t-test?
A Z-test requires the population standard deviation to be known in advance. A t-test is used when the standard deviation is estimated from your own sample data, which is the case for almost all dissertation and survey research.
What is the difference between a Z-test and a Z-score?
A Z-score standardizes a single data point, showing how many standard deviations it is from the mean. A Z-test is a full hypothesis test that evaluates whether an entire sample's mean differs significantly from a population value.
Can I use a Z-test with a small sample size?
Z-tests are generally reserved for larger samples, commonly n ≥ 30, so the sampling distribution approximates normal even if the underlying data isn't. With small samples and an unknown population standard deviation, a t-test is the appropriate choice instead.
How do I run a two-sample Z-test in R?
Use z.test(x = group1, y = group2, sigma.x = known_sd1, sigma.y = known_sd2, mu = 0) from the BSDA package. This compares the means of two independent groups when both population standard deviations are known — see the worked example above for full code and output.
Which R package should I use for a Z-test?
BSDA is the standard and most widely documented package for z.test() in R, covering both one-sample and two-sample cases. There's no separate "large dataset" variant needed — the Z-test calculation itself is computationally trivial regardless of n, so BSDA handles small and large samples equally well.
How do I calculate a Z-test manually in R without a package?
Calculate Z as (sample mean minus hypothesized mean) divided by (population standard deviation divided by the square root of sample size), then use pnorm() to find the corresponding p-value based on your alternative hypothesis.
How do I interpret the confidence interval from a Z-test in R?
If your hypothesized mean falls inside the reported confidence interval, the test will fail to reject the null hypothesis at the matching significance level — the CI and the p-value always agree. If the hypothesized value falls outside the interval, the test rejects the null. A narrower interval indicates a more precise estimate, typically from a larger sample or smaller variability.
What does it mean if my Z-test p-value is not significant?
A non-significant p-value means your sample didn't provide enough evidence to conclude the population mean differs from your hypothesized value. It does not prove the null hypothesis is true, only that it wasn't rejected.
Related Posts
Need this analysis done for your thesis or dissertation? I'll handle it in R, SPSS, or Minitab — with APA-formatted results delivered fast.