T-Test in R: One-Sample, Independent (Student & Welch) & Paired

Compare two means in R — one-sample, independent (Student & Welch) and paired t-tests, rstatix the modern way and base R for the classics, with the p-value drawn on the plot

Biostatistics

Learn to run a t-test in R three ways: one-sample (against a known mean), independent two-sample (Student and Welch), and paired. Use rstatix t_test() for a tidy result and base R t.test() for the classic output, check the normality and equal-variance assumptions, report the Cohen’s d effect size, and plot it with a ggpubr boxplot that prints the p-value.

Published

June 23, 2026

Modified

July 17, 2026

TipKey takeaways
  • A t-test compares means — one sample against a known value, or two groups against each other — and tells you whether the difference is statistically significant.
  • There are three forms: one-sample (mu =), independent (two unrelated groups), and paired (the same subjects measured twice). The independent test comes in Student (equal variances) and Welch (unequal — R’s safer default) flavors.
  • Use t_test() from rstatix for a tidy result, or base R t.test() for the classic printout — both wrap the same statistics.
  • Check the assumptions first: normality (shapiro_test() + Q-Q plot) and, for the Student test, equal variances (levene_test() / var.test()). If normality fails, switch to the Wilcoxon test.
  • Report the p-value (is it significant?) and the Cohen’s d effect size (how big?), and visualize it with ggpubr::ggboxplot() + stat_pvalue_manual().
Get the book — Comparing Groups: Numerical Variables (PDF)

Introduction

In a hurry? Jump to the t-test calculator ↓ — paste your own numbers and get the result.

A t-test answers one of the most common questions in data analysis: do two means differ, and is the difference real or just noise? It comes in three forms, picked by how your data is structured:

Test Compares Example
One-sample one group’s mean vs. a known value Is the mean mouse weight different from 25 g?
Independent (unpaired) the means of two unrelated groups Do men and women differ in weight?
Paired the same subjects measured twice Did the mice’s weight change before vs. after treatment?

This lesson runs all three the modern, pipe-friendly rstatix way with t_test(), shows the classic base-R t.test() equivalent, checks the assumptions that decide which test to trust, reports the Cohen’s d effect size, and visualizes the result with a ggpubr boxplot that prints the p-value on the panel. Each test uses its canonical demo dataset from the datarium package — mice (one-sample), genderweight (independent), and mice2 (paired).

Note

The hypotheses, in one line. A t-test pits a null hypothesis (the means are equal) against an alternative (they differ). For two groups: \(H_0: m_A = m_B\) vs. \(H_a: m_A \ne m_B\) (the default two-tailed test). To test a direction instead — \(m_A < m_B\) or \(m_A > m_B\) — pass alternative = "less" or "greater" (a one-tailed test).

t-Test calculator — paste your own data

Have your own numbers? Run a t-test right here — the calculation happens in your browser, so nothing is uploaded to a server. Pick the tab for your design, paste your values, and press Run.

How to use it. (1) Choose the tab: one sample (compare one group to a known value), two independent groups, or paired (two measurements on the same subjects). (2) Paste your numbers between the quotes — one value per line (straight from an Excel column); a decimal point (.) or a French decimal comma (,) both work. (3) Set the options in plain sight. (4) Press Run to get the statistic, degrees of freedom, p-value, confidence interval, the Cohen’s d effect size, and a boxplot. For two-sample, keep welch = TRUE unless the groups truly have equal variances; for one-sample, set mu to the reference value you’re testing against.

Under the hood the calculator calls run_t_test() — a small, dependency-light helper (base R + ggpubr). Prefer the raw t.test() call, step by step? It’s in the walkthrough below. You can also view / download the engine ▸ and reuse it in your own R.

Tip

Working with your real dataset? This calculator takes numbers you paste. To run the test on a whole data file — grouped, cleaned, and with the result explained in plain language plus a saved, shareable report — bring your data to Prova: the runtime is the judge.

Independent two-samples t-test

The independent (or unpaired) t-test compares the means of two unrelated groups — each subject belongs to exactly one group, and there’s no relationship between the observations across groups. We start here because it’s the most common case and gives us the hero plot.

We use the genderweight dataset — the weight of 40 individuals, 20 women and 20 men (the group column, F/M). The research question: is the average weight different between the two groups?

library(rstatix)

set.seed(123)
data("genderweight", package = "datarium")

# a couple of random rows per group
genderweight %>% sample_n_by(group, size = 2)
# A tibble: 4 × 3
  id    group weight
  <fct> <fct>  <dbl>
1 15    F       65.9
2 19    F       62.3
3 34    M       86.2
4 23    M       86.6

Summarize each group with get_summary_stats() — the count, mean and standard deviation you’ll report alongside the test:

library(rstatix)

data("genderweight", package = "datarium")

genderweight %>%
  group_by(group) %>%
  get_summary_stats(weight, type = "mean_sd")
# A tibble: 2 × 5
  group variable     n  mean    sd
  <fct> <fct>    <dbl> <dbl> <dbl>
1 F     weight      20  63.5  2.03
2 M     weight      20  85.8  4.35

Female weight averages about 63.5 (SD 2.03) and male about 85.8 (SD 4.3) — but always look before you test.

Look at the data first

ggpubr::ggboxplot() draws the boxes and jittered points so you can see the two distributions side by side:

library(ggpubr)

data("genderweight", package = "datarium")

ggboxplot(
  genderweight, x = "group", y = "weight",
  color = "group", palette = c("#3a86d4", "#8338ec"),
  add = "jitter", xlab = "Group", ylab = "Weight"
)

A boxplot of weight by gender group (F and M) with jittered points; the male group sits clearly higher than the female group with little overlap.

The male group sits well above the female group with little overlap — but the test is what makes the difference defensible.

Note

Student vs. Welch. The Student t-test assumes the two groups have equal variances and pools them; the Welch t-test does not — it uses each group’s own variance and adjusts the degrees of freedom (which is why Welch reports a fractional df). R uses Welch by default because it’s the safer choice, and the two give very similar results unless both the group sizes and the spreads differ a lot.

With base R

t.test() with the outcome ~ group formula computes the same test. It defaults to Welch; set var.equal = TRUE for Student:

data("genderweight", package = "datarium")

# Welch (default)
t.test(weight ~ group, data = genderweight)

    Welch Two Sample t-test

data:  weight by group
t = -20.791, df = 26.872, p-value < 2.2e-16
alternative hypothesis: true difference in means between group F and group M is not equal to 0
95 percent confidence interval:
 -24.53135 -20.12353
sample estimates:
mean in group F mean in group M 
       63.49867        85.82612 

Read the output: t and df are the test statistic and (fractional, for Welch) degrees of freedom, p-value is the significance, the 95 percent confidence interval brackets the difference in means, and the two mean values under sample estimates are the group means. The two functions agree number-for-number — rstatix just returns a tidy tibble. Pull individual values straight off a base-R result with res$p.value, res$statistic, and res$conf.int.

Plot it with the p-value on it

The publication-ready figure puts the test result on the plotadd_xy_position() works out where the bracket sits, stat_pvalue_manual() draws it, and get_test_label() prints the full t, df, p and effect-size line as a subtitle. This is the figure to report:

library(rstatix)
library(ggpubr)

data("genderweight", package = "datarium")

stat.test <- genderweight %>%
  t_test(weight ~ group) %>%
  add_significance() %>%
  add_xy_position(x = "group")

ggboxplot(
  genderweight, x = "group", y = "weight",
  color = "group", palette = c("#3a86d4", "#8338ec"),
  add = c("jitter", "mean"), xlab = "Group", ylab = "Weight"
) +
  stat_pvalue_manual(stat.test, tip.length = 0) +
  labs(subtitle = get_test_label(stat.test, detailed = TRUE))

A boxplot of weight by gender group (F versus M) with jittered points; the independent t-test statistic, degrees of freedom and p-value are printed as a subtitle and a significance bracket is drawn above the two boxes, which barely overlap.

The t-statistic is just a signal-to-noise ratio — the difference in means divided by its standard error:

\[t = \frac{\bar{x}_A - \bar{x}_B}{SE_d}\]

A bigger gap (or a smaller, more precise standard error) gives a larger \(t\), and a smaller p-value.

The two flavors differ in how they handle the spread and the degrees of freedom. The Student test pools both groups into one variance and uses \(df = n_A + n_B - 2\). The Welch test uses each group’s own variance and approximates \(df\) with the Satterthwaite formula — a fractional number (here ~26.9) that’s smaller than the pooled \(df\), which is why Welch is more conservative.

Cohen’s d answers a different question — not is the difference real? but how big is it? It’s the standardized mean difference: the gap in means expressed in standard-deviation units, \(d = (\bar{x}_A - \bar{x}_B) / SD\). That makes it comparable across studies and scales, unlike the raw difference or the p-value.

One-sample t-test

The one-sample t-test compares the mean of one group to a known or theoretical value mu. The theoretical mean usually comes from a previous study, or from a “percent of control” baseline of 100.

We use the mice dataset — the weight of 10 mice — and ask: is the average weight different from 25 g?

library(rstatix)

data("mice", package = "datarium")

mice %>% get_summary_stats(weight, type = "mean_sd")
# A tibble: 1 × 4
  variable     n  mean    sd
  <fct>    <dbl> <dbl> <dbl>
1 weight      10  20.1  1.90

The mice average about 20.1 g (SD 1.94) — visibly below 25, but the test tells us whether that gap is significant given the small sample.

With base R

t.test() takes the vector and the mu argument, and prints the classic, fuller report:

data("mice", package = "datarium")

t.test(mice$weight, mu = 25)

    One Sample t-test

data:  mice$weight
t = -8.1045, df = 9, p-value = 1.995e-05
alternative hypothesis: true mean is not equal to 25
95 percent confidence interval:
 18.78346 21.49654
sample estimates:
mean of x 
    20.14 

Read the output: t and df are the test statistic and degrees of freedom (df = n − 1 = 9), p-value is the significance, the 95 percent confidence interval brackets the true mean, and mean of x is the observed mean (~20.1). To test a one-sided hypothesis — “is the mean less than 25?” — add alternative = "less" (or "greater").

A boxplot of the single variable, with the reference value mu = 25 drawn in, shows what the test compares — the observed spread against the hypothesized mean:

library(rstatix)
library(ggpubr)

data("mice", package = "datarium")
stat.test <- mice %>% t_test(weight ~ 1, mu = 25)

ggboxplot(
  mice$weight, width = 0.5, add = c("mean", "jitter"),
  ylab = "Weight (g)", xlab = FALSE, color = "#3a86d4"
) +
  geom_hline(yintercept = 25, linetype = "dashed", color = "#8338ec") +
  labs(subtitle = get_test_label(stat.test, detailed = TRUE))

A boxplot of mouse weight with jittered points and the group mean marked, and a dashed horizontal line at 25 — the reference value the one-sample t-test compares the mean against; the data sit clearly below the line, with the one-sample test label printed as a subtitle.

Paired t-test

The paired t-test compares two measurements made on the same subjects — before/after, or two conditions on each unit. It works on the differences: compute each subject’s after − before, then test whether the mean difference is zero.

We use the mice2 dataset — the weight of 10 mice before and after a treatment, in wide format. A paired test wants the two measurements in one column, so reshape it to long with base R (stacking before and after into one weight column with a group factor):

library(rstatix)

data("mice2", package = "datarium")
head(mice2, 3)
  id before after
1  1  187.2 429.5
2  2  194.2 404.4
3  3  231.7 405.6
# wide → long: gather the before and after values into one column
mice2.long <- data.frame(
  id     = factor(rep(mice2$id, times = 2)),
  group  = factor(rep(c("before", "after"), each = nrow(mice2)), levels = c("before", "after")),
  weight = c(mice2$before, mice2$after)
)
head(mice2.long, 3)
  id  group weight
1  1 before  187.2
2  2 before  194.2
3  3 before  231.7
library(rstatix)

data("mice2", package = "datarium")
mice2.long <- data.frame(
  id     = factor(rep(mice2$id, times = 2)),
  group  = factor(rep(c("before", "after"), each = nrow(mice2)), levels = c("before", "after")),
  weight = c(mice2$before, mice2$after)
)

mice2.long %>%
  group_by(group) %>%
  get_summary_stats(weight, type = "mean_sd")
# A tibble: 2 × 5
  group  variable     n  mean    sd
  <fct>  <fct>    <dbl> <dbl> <dbl>
1 before weight      10  201.  20.0
2 after  weight      10  400.  30.1

With base R

The base-R equivalent uses the same formula with paired = TRUE:

data("mice2", package = "datarium")

# base R pairs by position — pass the two columns as vectors (the formula
# interface does not accept paired = TRUE)
t.test(mice2$before, mice2$after, paired = TRUE)

    Paired t-test

data:  mice2$before and mice2$after
t = -25.546, df = 9, p-value = 1.039e-09
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
 -217.1442 -181.8158
sample estimates:
mean difference 
        -199.48 

Here sample estimates is the mean of the differences, and the confidence interval brackets that difference — both numbers match the rstatix result.

Plot it with the p-value on it

ggpubr::ggpaired() is the natural plot for paired data: it draws the two boxes and connects each subject’s two measurements with a line, so the within-subject change is visible. Add the p-value the same way as the independent plot — add_xy_position() then stat_pvalue_manual():

library(rstatix)
library(ggpubr)

data("mice2", package = "datarium")
mice2.long <- data.frame(
  id     = factor(rep(mice2$id, times = 2)),
  group  = factor(rep(c("before", "after"), each = nrow(mice2)), levels = c("before", "after")),
  weight = c(mice2$before, mice2$after)
)

stat.test <- mice2.long %>%
  t_test(weight ~ group, paired = TRUE) %>%
  add_significance() %>%
  add_xy_position(x = "group")

ggpaired(
  mice2.long, x = "group", y = "weight",
  order = c("before", "after"),
  color = "group", palette = c("#3a86d4", "#8338ec"),
  line.color = "gray", line.size = 0.4,
  xlab = "Group", ylab = "Weight"
) +
  stat_pvalue_manual(stat.test, tip.length = 0) +
  labs(subtitle = get_test_label(stat.test, detailed = TRUE))

A paired boxplot of mouse weight before and after treatment, with a line connecting each of the 10 mice's two measurements and the paired t-test label printed as a subtitle with the significance bracket above; every line rises steeply from before to after.

The paired test is more powerful than the independent test when the pairing is real, because it removes the subject-to-subject variation — every mouse is its own control.

Warning

Pairing is a property of the data, not an option you choose. Use paired = TRUE only when each value in group 1 corresponds to a specific value in group 2 (same subject, matched pair). Applying it to genuinely independent groups is wrong and inflates significance.

Check the assumptions

The t-test is a parametric test. Beyond independent observations, it assumes the data (or, for the paired test, the differences) are approximately normal, the Student version additionally assumes equal variances, and there should be no significant outliers in either group.

Note

With large samples (n > 30) normality matters less — the central limit theorem keeps the test valid even when the raw data stray from normal. The checks below matter most for the small samples (n = 10) in the mice/mice2 examples.

Outliers

rstatix::identify_outliers() flags extreme values per group — an empty result (or is.extreme all FALSE) means no values would distort the means the test compares:

library(rstatix)

data("genderweight", package = "datarium")

genderweight %>%
  group_by(group) %>%
  identify_outliers(weight)
# A tibble: 2 × 5
  group id    weight is.outlier is.extreme
  <fct> <fct>  <dbl> <lgl>      <lgl>     
1 F     20      68.8 TRUE       FALSE     
2 M     31      95.1 TRUE       FALSE     

There were no extreme outliers.

Normality — Shapiro-Wilk + Q-Q

Test it with the Shapiro-Wilk test (p > 0.05 → no significant departure from normal). With rstatix, shapiro_test() checks each group at once via group_by():

library(rstatix)

data("genderweight", package = "datarium")

genderweight %>%
  group_by(group) %>%
  shapiro_test(weight)
# A tibble: 2 × 4
  group variable statistic     p
  <fct> <chr>        <dbl> <dbl>
1 F     weight       0.938 0.224
2 M     weight       0.986 0.989

Both p-values are above 0.05, so we cannot reject normality. Back it with ggpubr::ggqqplot(), which draws a Q-Q plot — the points should hug the reference line inside the confidence band:

library(ggpubr)

data("genderweight", package = "datarium")

ggqqplot(genderweight, x = "weight", facet.by = "group")

Two Q-Q plots side by side, one per gender group; in both, the points fall close to the diagonal reference line inside the confidence band, indicating approximate normality.

For a one-sample test, check the variable directly (mice %>% shapiro_test(weight)); for a paired test, check the differencesshapiro_test() on before − after — because it’s the differences that must be normal, not each raw measurement.

Equal variances (for the Student test)

The Student test assumes the two groups have equal variances. Check it with Levene’s test (p > 0.05 → variances are not significantly different, so Student is fine):

library(rstatix)

data("genderweight", package = "datarium")

genderweight %>% levene_test(weight ~ group)
# A tibble: 1 × 4
    df1   df2 statistic      p
  <int> <int>     <dbl>  <dbl>
1     1    38      6.12 0.0180

The base-R equivalent is the F-test var.test(weight ~ group, data = genderweight). Whatever the verdict, Welch (the default) is always the safer choice — it stays valid whether or not the variances match, which is exactly why R defaults to it.

Note

If normality fails (a significant shapiro_test(), or a Q-Q plot that strays from the line), use the non-parametric Wilcoxon test instead — swap t_test() for wilcox_test(), the formula is identical:

genderweight %>% wilcox_test(weight ~ group)

See the normality test lesson for the full assumption workflow.

Report the effect size (Cohen’s d)

A significant p-value tells you the difference is real; it does not tell you how big it is. For that, report Cohen’s d — the difference in means expressed in standard-deviation units. rstatix computes it with cohens_d(), which mirrors the t_test() call:

library(rstatix)

data("genderweight", package = "datarium")

# Effect size for the two-group comparison (Welch version)
genderweight %>% cohens_d(weight ~ group, var.equal = FALSE)
# A tibble: 1 × 7
  .y.    group1 group2 effsize    n1    n2 magnitude
* <chr>  <chr>  <chr>    <dbl> <int> <int> <ord>    
1 weight F      M        -6.57    20    20 large    

cohens_d() mirrors t_test() exactly: pass var.equal = TRUE for the pooled-SD (Student) version, mu = 25 for the one-sample version (cohens_d(weight ~ 1, mu = 25) on mice), or paired = TRUE for the paired version (cohens_d(weight ~ group, paired = TRUE) on mice2.long).

Cohen’s conventional benchmarks are 0.2 (small), 0.5 (moderate), and 0.8 (large) — so the d here is a very large effect. Always pair the p-value with the effect size: a tiny, trivial difference can be “significant” in a large sample, while a large effect can miss significance in a small one. The effect size has its own dedicated lesson — Cohen’s d effect size — covering the one-sample, independent and paired variants in depth.

Note

For small samples (< 50) the Cohen’s d tends to over-inflate. The Hedges’ corrected version (hedges_g() in rstatix) shrinks it by a few percent to compensate.

Interpret the result

Read three things from any t-test, in order:

  1. The p-value — is the difference statistically significant (typically p < 0.05)?
  2. The direction & confidence interval — which group is higher, and how precisely (does the CI of the difference exclude 0)?
  3. The effect size (Cohen’s d) — is the difference practically meaningful, not just detectable?

A complete report reads like: “The mean weight in the female group was 63.5 (SD = 2.03), versus 85.8 (SD = 4.3) in the male group. A Welch two-samples t-test showed the difference was statistically significant, t(26.9) = −20.8, p < 0.0001, d = 6.57.”

Try it live

Run the full workflow on a different comparison — mtcars fuel economy (mpg) by transmission type (am: 0 = automatic, 1 = manual). Edit the variables or the method and re-run; the sandbox boots on first Run.

🟢 With an AI agent

Ask Prova “should I use a paired or unpaired t-test for my data, and is the difference significant?” — it answers with rstatix code you can run on your own data, then helps you read the p-value and the effect size. The runtime is the judge. Ask Prova →

Common issues

t_test() could not find function / object. Load rstatix first — library(rstatix) — which also provides the %>% pipe used in these examples; and data("genderweight", package = "datarium") to make the dataset available.

My p-value differs from a colleague’s. Check var.equal. R (and rstatix) default to the Welch test, while some textbooks and other software default to the Student test (var.equal = TRUE). The two differ in their degrees of freedom (Welch’s is fractional) and so in the p-value.

A paired test gives a wildly different result from an unpaired one. That’s expected when the pairing is strong — the paired test removes subject-to-subject variation. Make sure paired = TRUE is correct for your design: each value in one group must correspond to a specific value in the other, and the two columns must be in the same subject order after you reshape to long.

Frequently asked questions

Yes — the calculator on this page runs a one-sample, two-sample (Student or Welch), or paired t-test on numbers you paste. It computes entirely in your browser with real R, so your data is never uploaded to any server, and it returns the t statistic, degrees of freedom, p-value, confidence interval, the Cohen’s d effect size and a boxplot — free, no sign-up.

A t-test compares means — one group against a known value, or two groups against each other. It tells you whether an observed difference is real or just the kind of difference you’d expect from random noise in your sample.

Use t_test() from rstatix (tidy output) or base R t.test() (classic printout). For two groups: data %>% t_test(outcome ~ group). For one sample against a known value: data %>% t_test(outcome ~ 1, mu = 25). For paired data add paired = TRUE. Both functions wrap the same statistics — rstatix just returns a tidy tibble you can drop straight onto a ggpubr plot.

An unpaired (independent) t-test compares two separate groups of subjects (e.g. men vs. women). A paired t-test compares two measurements on the same subjects (e.g. mouse weight before vs. after treatment) and tests the mean of the within-subject differences. Use paired only when each value in one group is matched to a specific value in the other; otherwise use unpaired.

Both are independent two-sample t-tests. The Student test assumes the two groups have equal variances and pools them; the Welch test does not — it uses each group’s own variance and adjusts the degrees of freedom (which is why its df is fractional). R uses Welch by default because it’s safer — set var.equal = TRUE to get the Student test. The two give very similar results unless the group sizes and the spreads differ substantially.

A two-tailed test (alternative = "two.sided", the default) asks only do the means differ? — in either direction. A one-tailed test asks a directional question: alternative = "less" tests whether group A’s mean is below group B’s, and alternative = "greater" whether it’s above. Use a one-tailed test only when you have a genuine prior reason to expect one direction (and commit to it before seeing the data); when in doubt, keep the default two-tailed test.

The data (or, for a paired test, the pairwise differences) should be approximately normally distributed — check with shapiro_test() and a Q-Q plot. The independent Student test also assumes equal variances (check with levene_test() or var.test()); the Welch test relaxes that. There should be no extreme outliers (identify_outliers()). With samples larger than ~30 the normality assumption matters less, thanks to the central limit theorem.

Use the non-parametric Wilcoxon test (Mann-Whitney for two independent groups, signed-rank for one-sample or paired) when the normality assumption fails — for example a significant shapiro_test(), a Q-Q plot that strays from the line, a small sample with extreme outliers, or ordinal data. The Wilcoxon test compares ranks (effectively medians) rather than means.

Test your understanding

  1. Run it. In the live cell below, compute an independent t-test of weight by group in genderweight, then add var.equal = TRUE. Does the p-value change much? Why?
  2. Conceptual. You measured each mouse’s weight before and after a treatment, in the same animals. Which t-test should you use — and what would you check before trusting it?

The grouping variable is group, so the formula is weight ~ group. The first call (no var.equal) is the Welch test; for the Student test set var.equal = TRUE. For question 2, “same animals measured twice” is the signature of a paired design.

library(rstatix)
library(datarium)
data("genderweight", package = "datarium")
genderweight %>% t_test(weight ~ group)                   # Welch (default)
genderweight %>% t_test(weight ~ group, var.equal = TRUE) # Student
#> Both are highly significant (p < 0.0001); the df differs (Welch's is fractional, ~26.9).

The two p-values are both far below 0.05 — the difference is large and obvious either way. The Welch and Student df differ (Welch’s is fractional) because Welch does not pool the variances.

For question 2: use a paired t-test (paired = TRUE), because each “after” value belongs to the same mouse as its “before” value. Before trusting it, compute the differences (after − before) and check that those are approximately normal with shapiro_test() and a Q-Q plot; if normality fails, use the paired Wilcoxon signed-rank test instead.

Conclusion

You can now run and interpret a t-test in R in all three forms — one-sample (t_test(y ~ 1, mu =)), independent (Student vs. Welch, R’s safer default), and paired (paired = TRUE) — the tidy rstatix way and the classic base-R way. Check normality (and, for Student, equal variances) before you trust the result, read the p-value for significance, and report Cohen’s d for the size of the effect — always with the boxplot, p-value on the panel, in view.

Reuse

Citation

BibTeX citation:
@online{2026,
  author = {},
  title = {T-Test in {R:} {One-Sample,} {Independent} {(Student} \&
    {Welch)} \& {Paired}},
  date = {2026-06-23},
  url = {https://www.datanovia.com/learn/biostatistics/two-groups/t-test-in-r},
  langid = {en}
}
For attribution, please cite this work as:
“T-Test in R: One-Sample, Independent (Student & Welch) & Paired.” 2026. June 23. https://www.datanovia.com/learn/biostatistics/two-groups/t-test-in-r.