Descriptive Statistics in R: Summarise and Describe Your Data

Central tendency, variability and grouped summaries — mean, median, mode, range, IQR, variance and SD — the modern way with rstatix and base R

Biostatistics

Learn to compute descriptive statistics in R — the measures of central tendency (mean, median, mode) and variability (range, interquartile range, variance, standard deviation) — with base R and the pipe-friendly rstatix get_summary_stats(), including grouped summaries and a quick visual.

Published

June 23, 2026

Modified

July 7, 2026

TipKey takeaways
  • Descriptive statistics summarise a dataset with a few numbers and a plot — the first step before any test.
  • Central tendency: mean(), median(), and the mode (most frequent value — no base function, so compute it from a frequency table).
  • Variability: range()/min()/max(), the interquartile range IQR(), the variance var() and the standard deviation sd().
  • The pipe-friendly rstatix::get_summary_stats() computes all of these at once, and by group with group_by().
  • Pair the numbers with a boxplot or histogram — a summary table and a picture together tell the story.

Introduction

Descriptive statistics describe and summarise your data before you test anything — the shape of a distribution, where it is centred, and how spread out it is. They split into two families:

  • Measures of central tendency — where the data cluster: the mean, the median, and the mode.
  • Measures of variability (dispersion) — how spread out it is: the range, the interquartile range, the variance and the standard deviation.

This lesson computes each with base R and with the pipe-friendly rstatix get_summary_stats(), using the built-in iris data.

Central tendency: mean, median, mode

The mean and median have base-R functions; the mode (most frequent value) does not, so we read it off a frequency table:

x <- iris$Sepal.Length

mean(x)     # arithmetic mean
[1] 5.843333
median(x)   # middle value (robust to outliers)
[1] 5.8
# mode: the most frequent value (base R)
freq <- table(x)
as.numeric(names(freq)[which.max(freq)])
[1] 5

The mean (5.84) and median (5.80) are close, indicating a fairly symmetric distribution; the mode is the single most common value.

Tip

Mean vs median. The mean uses every value, so it is pulled by outliers; the median is the middle value, so it is robust. When they diverge sharply, the distribution is skewed — a cue to check normality or consider a transformation.

Variability: range, IQR, variance, SD

x <- iris$Sepal.Length

range(x)    # min and max
[1] 4.3 7.9
IQR(x)      # interquartile range (Q3 - Q1), robust spread
[1] 1.3
var(x)      # variance
[1] 0.6856935
sd(x)       # standard deviation (sqrt of variance)
[1] 0.8280661

The standard deviation (0.83) is the most reported measure of spread — the typical distance of a value from the mean, in the original units. The IQR (the middle 50%) is its robust counterpart, unaffected by extreme values.

All at once: get_summary_stats()

rstatix::get_summary_stats() returns the common summaries in one tidy table — choose the set with type ("common", "mean_sd", "median_iqr", "full"):

library(rstatix)

iris %>% get_summary_stats(Sepal.Length, type = "common")
# A tibble: 1 × 10
  variable         n   min   max median   iqr  mean    sd    se    ci
  <fct>        <dbl> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Sepal.Length   150   4.3   7.9    5.8   1.3  5.84 0.828 0.068 0.134

Grouped summaries

The real power is per group — pipe group_by() first to summarise each species at once:

library(rstatix)

iris %>%
  group_by(Species) %>%
  get_summary_stats(Sepal.Length, type = "mean_sd")
# A tibble: 3 × 5
  Species    variable         n  mean    sd
  <fct>      <fct>        <dbl> <dbl> <dbl>
1 setosa     Sepal.Length    50  5.01 0.352
2 versicolor Sepal.Length    50  5.94 0.516
3 virginica  Sepal.Length    50  6.59 0.636

This is the table behind every group comparison — the means and SDs you report alongside a t-test or ANOVA.

Visualise the summary

Numbers and a picture together. A boxplot shows the median, IQR and outliers per group; add the mean and jittered points:

library(ggpubr)

ggboxplot(iris, x = "Species", y = "Sepal.Length",
          add = c("mean", "jitter"), color = "Species", palette = "jco",
          ylab = "Sepal length", xlab = "Species")

A boxplot of iris sepal length by species with the mean marked and individual points jittered; virginica is highest, setosa lowest, with clear separation.

Try it live

Summarise a different variable or dataset. The sandbox boots on first Run.

🟢 With an AI agent

Ask Prova “summarise my data — give me the mean, median, SD and IQR for each group, and a plot to go with it” — it answers with rstatix code you can run on your own data. The runtime is the judge. Ask Prova →

Common issues

There is no mode() function for the most frequent value. Base R’s mode() returns the storage type of an object, not the statistical mode. Compute the statistical mode from a frequency table: names(which.max(table(x))).

Missing values give NA. mean(x), sd(x) and friends return NA if x contains NA. Add na.rm = TRUE (e.g. mean(x, na.rm = TRUE)); get_summary_stats() handles missing values for you.

You reported the variance instead of the SD. The variance is in squared units; the standard deviation (its square root) is in the original units and is what readers expect — report sd().

Frequently asked questions

Use rstatix: data %>% group_by(grouping_var) %>% get_summary_stats(variable, type = "mean_sd"). It returns one row per group with the chosen statistics (count, mean, SD, median, IQR, etc.). This is the standard way to produce the descriptive table that accompanies a t-test or ANOVA.

The mean is the arithmetic average (sum ÷ count) and uses every value, so outliers pull it. The median is the middle value when sorted, so it is robust to outliers and skew. When they differ a lot, the distribution is skewed — the median is the better summary of “typical”.

There is no built-in statistical-mode function (mode() returns the object’s type). Build a frequency table and take the most frequent: names(which.max(table(x))). For a numeric vector wrap it in as.numeric().

Report the standard deviation in most contexts — it is the square root of the variance and is expressed in the original units, so it is directly interpretable as the typical distance from the mean. The variance (squared units) is mainly an intermediate quantity.

Test your understanding

  1. Run it. In the live cell, compute the mean and standard deviation of iris$Petal.Length, then a grouped get_summary_stats() by species. Fill the blank.
  2. Conceptual. For a strongly right-skewed income variable, which measure of central tendency best describes the “typical” value, and why?

Fill the blank with Species. For question 2, recall which measure is robust to the long tail of a skewed distribution.

iris %>% group_by(Species) %>% get_summary_stats(Petal.Length, type = "mean_sd")
#> one row per species with n, mean and sd.

For question 2: the median. Income is strongly right-skewed (a few very high earners), which inflates the mean; the median (the middle value) is unaffected by the long tail and better represents the typical person.

Conclusion

You can now compute descriptive statistics in R: central tendency (mean(), median(), and the mode from a frequency table) and variability (range(), IQR(), var(), sd()), or all of them at once — and by group — with rstatix::get_summary_stats(). Pair the table with a boxplot or histogram, and you have the summary that opens every analysis and accompanies every test.

Reuse

Citation

BibTeX citation:
@online{2026,
  author = {},
  title = {Descriptive {Statistics} in {R:} {Summarise} and {Describe}
    {Your} {Data}},
  date = {2026-06-23},
  url = {https://www.datanovia.com/learn/biostatistics/assumptions/descriptive-statistics-in-r},
  langid = {en}
}
For attribution, please cite this work as:
“Descriptive Statistics in R: Summarise and Describe Your Data.” 2026. June 23. https://www.datanovia.com/learn/biostatistics/assumptions/descriptive-statistics-in-r.