Written and maintained by CASRAI Editorial Board
Last updated
Hypothesis testing with R comes down to four base-R functions: t.test() for means, wilcox.test() for a rank-based alternative, chisq.test() for counts, and shapiro.test() for checking normality. Each returns an object of class “htest”, so once you can read one, you can read all of them. This page is the map: which function answers which question, the arguments that change the answer, and where the numbers sit in the result.
For the logic behind choosing between hypotheses, see CASRAI’s comparison of null and alternative hypotheses and the guide to two-tailed hypothesis testing.
What it is used for in research
R’s stats package, which ships with R, holds the standard classical tests. In a typical study you use them to compare a group mean with a reference value, compare two groups or two measurements on the same units, or test whether categorical counts depart from what a model predicts. The general idea of a statistical test is the same in every case; what changes is the function and its arguments.
Which function answers which question
| Question | Function | Arguments that change the answer | Notes from the R manual |
|---|---|---|---|
| Is a mean different from a value, or are two means different? | t.test() |
alternative (“two.sided”, “less”, “greater”), mu, paired, var.equal, conf.level |
Default var.equal = FALSE, so the Welch (Satterthwaite) approximation to the degrees of freedom is used. |
| Same question without assuming a normal shape? | wilcox.test() |
alternative, mu, paired, exact, correct, conf.int |
With exact unspecified, an exact p-value is computed for fewer than 50 finite values, otherwise a normal approximation is used. |
| Do category counts match expected proportions, or are two categorical variables associated? | chisq.test() |
correct, p, rescale.p, simulate.p.value, B |
The continuity correction applies only to 2-by-2 tables. |
| Does a sample look normally distributed? | shapiro.test() |
Only x |
Performs the Shapiro-Wilk test of normality; the number of non-missing values must be between 3 and 5000. |
Install or access
Download R from CRAN, the Comprehensive R Archive Network. As of 2026-10-29 the Windows download page at cran.r-project.org/bin/windows/base offers R 4.6.1. All four functions on this page are in the stats package, so there is nothing further to install.
Step-by-step: test a hypothesis in R
- State the hypotheses. Write the null and the alternative before you touch the data. Your alternative decides the
alternativeargument: “two.sided” for any difference, “less” or “greater” for a directional claim. A directional claim needs a reason set in advance. - Check the assumption you are about to lean on. If you plan a t-test and want to check normality, run
shapiro.test(x)on the values. It needs between 3 and 5000 non-missing values. - Run the test. Examples follow, each taken from the R manual’s own examples.
# Two samples, vector interface t.test(1:10, y = c(7:20)) # Two groups, formula interface (mtcars is built into R) t.test(mpg ~ am, data = mtcars) # One sample against mu = 0 (sleep is built into R) t.test(extra ~ 1, data = sleep) # Paired data, formula form (sleep2 is the built-in sleep data reshaped to wide format, with columns extra.1 and extra.2, as in the manual's example) t.test(Pair(extra.1, extra.2) ~ 1, data = sleep2) # Paired, rank-based, one-sided x <- c(1.83, 0.50, 1.62, 2.48, 1.68, 1.88, 1.55, 3.06, 1.30) y <- c(0.878, 0.647, 0.598, 2.05, 1.06, 1.29, 1.06, 3.14, 1.29) wilcox.test(x, y, paired = TRUE, alternative = "greater") - Test counts. For a table of counts, pass the table:
M <- as.table(rbind(c(762, 327, 468), c(484, 239, 477))) dimnames(M) <- list(gender = c("F", "M"), party = c("Democrat", "Independent", "Republican")) Xsq <- chisq.test(M) Xsq$expected Xsq$residuals Xsq$stdres # Goodness of fit against stated proportions x <- c(89, 37, 30, 28, 2) p <- c(40, 20, 20, 15, 5) chisq.test(x, p = p, rescale.p = TRUE)The table example is from the manual (after Agresti, 2007). If your data are a raw vector of categories rather than counts, pass
table(x), not the raw vector. - Read the result as described below, and report the statistic, the degrees of freedom where there are any, the p-value, and the confidence interval or effect estimate.
Output and how to read it
Each of these functions returns an “htest” object. For t.test() the manual lists these components: statistic, parameter (the degrees of freedom), p.value, conf.int, estimate, null.value, stderr, alternative, method and data.name. You can store the result and pull out a component by name, for example:
res <- t.test(mpg ~ am, data = mtcars)
res$p.value
res$conf.int
res$estimate
For chisq.test() the returned object also carries observed, expected, residuals (Pearson residuals, (O – E) / sqrt(E)) and stdres. Looking at the residuals shows which cells drive a significant result, which the single p-value cannot. The manual’s own two-sample example, t.test(1:10, y = c(7:20)), reports p = .00001855.
A p-value tells you how surprising the data would be if the null were true; it does not give the size or importance of an effect. Pair it with the confidence interval, and see the guide to finding a critical value if you want the cutoff version of the same decision.
Troubleshooting
My t-test degrees of freedom are not whole numbers
That is the Welch approximation, which t.test() uses by default because var.equal is FALSE. Set var.equal = TRUE only if you have a reason to assume equal variances and want the pooled version.
My paired data give the wrong answer
Both samples are treated as independent unless you set paired = TRUE (or use the Pair() formula form shown above). The same paired argument exists in wilcox.test().
wilcox.test() and ties
The manual describes the exact test under ties as using the conditional (permutation) distribution, and suggests digits.rank = 7 when tiny differences are creating spurious ties. For the full method see CASRAI’s guide to the Wilcoxon test in R.
The continuity correction changed my chi-square result
correct = TRUE is the default, and the correction applies only to 2-by-2 tables. It is not used when simulate.p.value = TRUE. Set correct = FALSE to see the uncorrected statistic.
chisq.test() on raw data gives an error or nonsense
Pass counts. For a raw vector of categories, wrap it in table() first.
shapiro.test() refuses my sample
It accepts only 3 to 5000 non-missing values. See the guide to the Shapiro-Wilk test in R for the full use of that test.
Where to go next for each test
This page is the overview. For a dedicated walk-through of one test in R, see running a t-test in R, the Wilcoxon test in R, the Kruskal-Wallis test in R, and the dictionary entry on the chi-square test.
FAQ
Which R function should I use for hypothesis testing?
Use t.test() to compare means, wilcox.test() for a rank-based alternative, chisq.test() for counts, and shapiro.test() to check normality. The table above matches each question to a function.
How do I get the p-value out of an R test?
Save the result to a variable and read its p.value component, for example res$p.value. The same works for statistic, conf.int and estimate where the test returns them.
How do I run a one-sided test in R?
Set alternative = "less" or alternative = "greater". The default is “two.sided”. The functions t.test() and wilcox.test() both take this argument.
Does t.test() assume equal variances?
No. The default is var.equal = FALSE, which uses the Welch (Satterthwaite) approximation to the degrees of freedom.
Sources
Date checked: 2026-10-29.
- R Documentation, stats package: t.test
- R Documentation, stats package: wilcox.test
- R Documentation, stats package: chisq.test
- R Documentation, stats package: shapiro.test
- CRAN: Download R for Windows








