Written and maintained by CASRAI Editorial Board
Last updated
Summary statistics in R are produced by three common calls: summary(), which ships with base R, skim() from the skimr package and describe() from the psych package. All three take a data frame and return one row of statistics per variable, but they differ in which statistics they report, how they treat missing values and whether they can summarise by group. This guide gives the exact calls from each package’s documentation, shows how to read the output and compares the three so you can pick one for your analysis.
What it is used for in research
Summary statistics are the first check on a dataset: the centre, spread and range of each variable, plus how many values are missing. Researchers run them before any test or model to catch impossible values, empty columns and variables stored as the wrong type. They also feed the descriptive table that most papers report. For the definitions behind the numbers, see descriptive statistics, standard deviation in R and interquartile range in R.
Install or access (official source only)
R itself is distributed from CRAN, the Comprehensive R Archive Network, at cran.r-project.org. The summary() function is part of base R, so it needs no installation. skimr and psych are CRAN packages, installed once and loaded in each session:
install.packages("skimr")
install.packages("psych")
library(skimr)
library(psych)
The skimr documentation also gives a development version, installed with devtools::install_github("ropensci/skimr"); most analyses should use the CRAN release. If you work inside an editor, how to use RStudio explains the console and script panes where these commands are typed.
Step-by-step: summarise a data frame
The steps below use iris, a data frame that comes with R, so they run without importing anything.
- Start with base R. Run
summary(iris). For a data frame, the R manual says the result is a matrix of classtableobtained by applyingsummaryto each column. - Control the display. The data frame method accepts
maxsum(default 7) anddigits(defaultmax(3, getOption("digits")-3)). The manual’s own example issummary(attenu, digits = 4), and for a single factor,summary(attenu$station, maxsum = 20)lists more levels. - Summarise one variable. Run
summary(iris$Sepal.Length). A single numeric vector uses the default method, which returns an object of classsummaryDefaultandtable. - Get a fuller overview with skimr. Run
skim(iris). To limit it to chosen columns, name them:skim(iris, Sepal.Length, Petal.Length). - Get psych’s statistics. Run
describe(iris). The function reports statistics for each column; its documentation lists the arguments you can change, such asna.rm,trim,typeandIQR. - Repeat by group. With skimr, group first with dplyr:
iris |> dplyr::group_by(Species) |> skim(). With psych, usedescribeBy(iris, iris$Species), or the formula form shown in its manual, such asdescribeBy(SATV + SATQ ~ gender, data = sat.act).
Output and how to read it
What summary() reports
For a numeric variable the manual’s example comment says the output “includes quantile(), mean, and NAs (if any)”, so you read the minimum, quartiles, mean and maximum, and a count of missing values only when some exist. The quartiles are computed with quantile(*, type = quantile.type), and quantile.type defaults to 7. This matters when you compare results across software: the manual’s example sets quantile.type = 8, so the type is a real choice, and quartiles from a package that uses a different definition can differ slightly from R’s default. Report which one you used. The related guides on the interquartile range in R and box plots in R use the same quartiles.
For a factor, the manual states that “the frequency of the first maxsum – 1 most frequent levels is shown”, with maxsum defaulting to 100 for factors. For a logical vector the manual example comment says the summary “shows NAs (if any) and the mode()”, while table(lvec) “excludes NAs by default”.
What skim() reports
The skimr documentation lists these columns for numeric variables: skim_variable, n_missing, complete_rate, mean, sd, p0, p25, p50, p75, p100 and hist. The last column is a small text histogram built from block characters. Here p0 is the minimum, p50 the median and p100 the maximum, so one line gives you the standard deviation, the quartiles and the missing count together. Read n_missing and complete_rate first: they tell you whether a variable is usable before you look at its centre.
What describe() reports
The psych manual lists the value columns as item name and number, the number of valid cases, mean, standard deviation, trimmed mean, median, median absolute deviation (mad), minimum, maximum, skew, kurtosis and standard error. Skew and kurtosis use type = 3 unless you change it, and na.rm defaults to TRUE, so the count of valid cases (n) is the number of non-missing values for that variable. Use that column to see how many observations each statistic is based on. Skew and kurtosis help you judge shape alongside a check for outliers in R.
Troubleshooting
Missing values
The tools handle them differently. summary() shows an NA count when there are any. skim() always gives n_missing and complete_rate. describe() removes them by default (na.rm = TRUE), so compare its n column with your row count before you report results.
Too few or too many digits
Set digits in summary(). The manual notes that the default method uses signif() and the data frame method uses format(), so the same number of digits can appear differently in the two.
Character columns
The manual documents character.method for the default method, for example summary(month.name, character.method = "factor"), which asks for a factor-style summary of a character vector. If a text column is really a category, converting it to a factor gives you the factor summary directly.
Grouped output is a list
describeBy() returns a list by default; its mat argument asks for matrix output instead, with digits controlling the rounding (15 by default). Use mat = TRUE when you want one table to export.
The function is not found
Errors such as “could not find function skim” or “describe” usually mean the package was installed but not loaded in this session. Run library(skimr) or library(psych) first.
Free alternatives (table)
The table compares the three calls as their documentation describes them.
| Feature | summary() | skimr::skim() | psych::describe() |
|---|---|---|---|
| Where it comes from | Base R | CRAN package skimr | CRAN package psych |
| Statistics for numeric variables | Quantiles and mean | Mean, sd, p0, p25, p50, p75, p100 and a text histogram | n, mean, sd, trimmed mean, median, mad, min, max, skew, kurtosis, se |
| Missing values | NA count shown if any | n_missing and complete_rate |
Removed by default (na.rm = TRUE); n counts valid cases |
| Main controls | digits, maxsum, quantile.type |
Name the columns to include | trim, type, quant, IQR, ranges |
| By-group summary | Not a documented argument of this function | Group with dplyr::group_by(), then skim() |
describeBy() |
For other free software for descriptive work, see free statistical software; what R is used for shows summary() on a real example.
FAQ
How do I get summary statistics for a whole data frame in R?
Pass the data frame to summary(), skim() or describe(). Each returns one set of statistics per column; summary(df) needs no package, while the other two need library(skimr) or library(psych).
Which function should I use for a research paper’s descriptive table?
The one whose statistics match what you will report. describe() gives n, mean, sd, median, skew and kurtosis in one row; skim() adds the missing counts; summary() gives the quartiles. Whichever you pick, state the package and, for quartiles, the quantile type.
How do I get summary statistics by group?
Use describeBy(data, group) from psych, or dplyr::group_by() followed by skim() from skimr, as in the steps above.
Why do my quartiles differ from another program?
R’s summary() uses quantile.type = 7 by default, and the documentation lets you change the type. A different default in other software can give slightly different quartiles from the same data.
Sources (official docs)
- R Core Team, R manual, summary {base}: stat.ethz.ch/R-manual/R-devel/library/base/html/summary.html (R-devel manual, checked 2026-10-29).
- skimr documentation, rOpenSci: docs.ropensci.org/skimr (version 2.2.2 shown, checked 2026-10-29).
- psych manual, describe: search.r-project.org/CRAN/refmans/psych/html/describe.html (checked 2026-10-29).
- psych manual, describeBy: search.r-project.org/CRAN/refmans/psych/html/describe.by.html (checked 2026-10-29).
- CRAN package page for psych (version 2.6.9, published 2026-09-30): cran.r-project.org/package=psych (checked 2026-10-29).








