# F-Test in R: How to Compare Variances (With Example)

An r f-test compares the variances of two samples to test whether the populations they come from have equal spread. In R you run it with `var.test()`, which returns an F statistic, two degrees of freedom, a p-value, and a confidence interval for the ratio of variances. This article walks through the test on a small dataset and shows how to read every part of the output.

## Quick Answer

- Use `var.test(x, y)` to compare the variances of two numeric vectors [1].
- The null hypothesis is that the ratio of the two population variances equals 1, meaning the variances are equal [1].
- The test statistic is $F = s_1^2 / s_2^2$, the ratio of the two sample variances [1].
- The default alternative is `"two.sided"`, so a small p-value means the variances differ in either direction [1].
- The output also gives a confidence interval for the true ratio of population variances [1].

## Before You Start

The F-test for variances assumes both samples come from normal distributions. If the data are strongly skewed or have outliers, the p-value can be misleading, and a nonparametric test for difference in scale is a better choice [1].

You need two numeric vectors of data values, or two fitted linear models. The function signature is `var.test(x, y, ratio = 1, alternative = "two.sided", conf.level = 0.95, ...)` [1]. The `ratio` argument is the hypothesized ratio of population variances under the null, and it defaults to 1 [1]. The `alternative` argument accepts `"two.sided"`, `"greater"`, or `"less"`, and you can specify just the initial letter [1].

The test is sensitive to sample size. Small samples give wide confidence intervals and low power, so a non-significant result does not prove the variances are equal.

## Step by Step

1. **Load your two samples.** Put each group in its own numeric vector. Missing values are handled by the usual R rules, so check for `NA` before you run the test.

2. **Check the shape of each sample.** Plot the data or compute skewness. The F-test assumes normality, so look at this before trusting the p-value.

3. **Run the test.** Call `var.test(g1, g2)` for a two-sided test of equal variances [1].

4. **Read the F statistic.** It is the ratio of the first sample variance to the second, $F = s_1^2 / s_2^2$ [1]. A value near 1 supports equal variances.

5. **Read the degrees of freedom.** The numerator df is $n_1 - 1$ and the denominator df is $n_2 - 1$ [1].

6. **Read the p-value.** Compare it to your alpha, usually 0.05. A p-value below alpha means you reject the null of equal variances [1].

7. **Read the confidence interval.** It gives a range for the true ratio of population variances [1]. If the interval excludes 1, the variances differ at that confidence level.

8. **Report the result.** State the F statistic, both degrees of freedom, the p-value, and the interval.

## Worked Example

The dataset holds two groups of lab measurements with 10 observations each.

| group | value |
|---|---|
| Group 1 | 10.2 |
| Group 1 | 11.4 |
| Group 1 | 9.8 |
| Group 1 | 12.1 |
| Group 1 | 10.9 |
| Group 1 | 11.0 |
| Group 1 | 10.5 |
| Group 1 | 9.9 |
| Group 1 | 11.7 |
| Group 1 | 10.6 |
| Group 2 | 14.1 |
| Group 2 | 12.3 |
| Group 2 | 16.8 |
| Group 2 | 13.5 |
| Group 2 | 15.2 |
| Group 2 | 11.9 |
| Group 2 | 17.4 |
| Group 2 | 14.6 |
| Group 2 | 13.0 |
| Group 2 | 15.7 |

The sample variance for Group 1 is $s_1^2 = 0.5788$ and for Group 2 is $s_2^2 = 3.4028$. The F statistic is the ratio:

$$F = \frac{s_1^2}{s_2^2} = \frac{0.5788}{3.4028} = 0.1701$$

Both samples have 10 observations, so $df_1 = 9$ and $df_2 = 9$. The two-sided p-value from the F distribution with 9 and 9 degrees of freedom is 0.0145. The 95% confidence interval for the variance ratio is [0.0422, 0.6848]. At alpha = 0.05 the p-value is below the threshold, so you reject the null hypothesis and conclude the variances differ.

```r
g1 <- c(10.2, 11.4, 9.8, 12.1, 10.9, 11.0, 10.5, 9.9, 11.7, 10.6)
g2 <- c(14.1, 12.3, 16.8, 13.5, 15.2, 11.9, 17.4, 14.6, 13.0, 15.7)
var.test(g1, g2)
```

```
	F test to compare two variances

data:  g1 and g2
F = 0.17009, num df = 9, denom df = 9, p-value = 0.01452
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
 0.04224790 0.68478052
sample estimates:
ratio of variances 
         0.1700898
```

The interval [0.0422, 0.6848] sits entirely below 1, which agrees with the p-value. Group 2 is more variable than Group 1. If you want to see how the two distributions look side by side, a quick summary of central tendency helps, and the median in R is a good companion measure when the data are skewed.

## Other Ways to Do It

You can pass fitted linear models instead of raw vectors. `var.test(lm(x ~ 1), lm(y ~ 1))` gives the same result as `var.test(x, y)` [1].

You can use the formula interface when your data are in a data frame with a grouping column. The formula takes the form `lhs ~ rhs`, where `lhs` is the numeric variable and `rhs` is a factor with two levels [1]. For example, `var.test(value ~ group, data = df)` runs the test directly on the grouped data.

You can change the alternative hypothesis with `alternative = "greater"` or `alternative = "less"` when you have a directional question [1]. You can also set `conf.level` to something other than 0.95 [1].

For more than two groups, `var.test()` does not apply. Use `bartlett.test()` for testing homogeneity of variances across more than two samples from normal distributions [1].

## Troubleshooting

**The function errors on non-numeric input.** `var.test()` needs numeric vectors or fitted models. Convert factors or character columns to numeric first.

**You get a "not enough observations" error.** This means one sample has fewer than two non-missing values, so its variance cannot be computed. `var.test()` drops non-finite values first, so check how many values remain in each group.

**The p-value looks strange for tiny samples.** With very small n, the F distribution is wide and the test has little power. Report the confidence interval alongside the p-value.

**The formula interface fails.** Make sure the right-hand side is a factor with exactly two levels. A factor with three or more levels is not supported by `var.test()` [1].

**The result disagrees with a Levene or Fligner test.** Those tests do not assume normality, so they can differ when the data are skewed. Trust the nonparametric result in that case [1].

## Common Mistakes

- **Swapping the order of the vectors.** The F statistic is $s_1^2 / s_2^2$, so `var.test(g2, g1)` gives the reciprocal, about 5.88 instead of 0.1701. Keep the order consistent with how you report the ratio.
- **Ignoring the normality assumption.** The F-test is sensitive to non-normal data. Plot the samples first, and switch to a nonparametric scale test if the data are skewed [1].
- **Reading a non-significant p-value as proof of equal variances.** Failing to reject the null does not mean the variances are equal. It means you lacked evidence against equality.
- **Forgetting that the default is two-sided.** If you have a directional hypothesis, set `alternative` explicitly, or you will test the wrong thing [1].
- **Using `var.test()` for three or more groups.** It only compares two samples. Use `bartlett.test()` for more than two groups from normal distributions [1].
- **Reporting the p-value without the interval.** The confidence interval for the variance ratio shows the size of the effect, which the p-value alone hides [1].

## Limitations

The F-test assumes both populations are normal. When that assumption fails, the test can produce p-values that are too small or too large, and you may reject or fail to reject the null for the wrong reason. It is also sensitive to outliers, since variances are computed from squared deviations.

The test only compares two variances at a time. It cannot handle three or more groups, and it does not tell you which group is more variable in a practical sense, only whether the ratio differs from the hypothesized value. For skewed data, consider a nonparametric two-sample test for difference in scale instead [1].

## Frequently Asked Questions

### What does the F-test for variances actually test?

It tests whether the ratio of two population variances equals a hypothesized value, which defaults to 1 [1]. The null hypothesis is that the two variances are equal. A small p-value means the observed ratio is unlikely if the variances were truly equal.

### How do I interpret the F statistic in R?

The F statistic is the ratio of the first sample variance to the second [1]. A value of 1 means the sample variances are equal. Values far from 1, in either direction, suggest the population variances differ.

### What is the difference between `var.test()` and `bartlett.test()`?

`var.test()` compares exactly two variances [1]. `bartlett.test()` tests homogeneity of variances across more than two samples from normal distributions [1]. Use `var.test()` for a two-group comparison and `bartlett.test()` when you have three or more groups.

### Can I run an F-test on non-normal data?

You can run it, but the result may be unreliable. The test assumes normality, and skewed data or outliers distort the p-value. For non-normal data, use a nonparametric two-sample test for difference in scale [1].

### Why is my confidence interval so wide?

Wide intervals come from small samples. With 10 observations per group, the interval for the variance ratio spans a broad range. Collect more data if you need a tighter estimate of the ratio.

## References

1. [R: F Test to Compare Two Variances](https://stat.ethz.ch/R-manual/R-devel/library/stats/html/var.test.html)

## Further Reading

- [Wickham H (2014). Tidy Data. Journal of Statistical Software](https://doi.org/10.18637/jss.v059.i10)
- [Wickham H, Averick M, Bryan J et al. (2019). Welcome to the Tidyverse. Journal of Open Source Software](https://doi.org/10.21105/joss.01686)
- [An Introduction to R (R Core Team)](https://cran.r-project.org/doc/manuals/r-release/R-intro.html)
- [Wickham H, Cetinkaya-Rundel M, Grolemund G. R for Data Science (2e)](https://r4ds.hadley.nz/)
- [ggplot2 Reference](https://ggplot2.tidyverse.org/reference/index.html)

## Related Articles

- [Likelihood Ratio Test: Definition, Formula and Examples](/blog/data-analysis/likelihood-ratio-test)
- [How to Find the Median in R (With Examples)](/blog/data-analysis/median-in-r)
- [ifelse in R: Vectorized If-Else With Examples](/blog/data-analysis/ifelse-in-r-vectorized-examples)
- [R letters Function: Generate Lowercase Letter Sequences](/blog/data-analysis/r-letters-function)
- [R ones: How to Create a Vector of Ones in R](/blog/data-analysis/r-ones-vector)