Skip to main content
v2026.11,858 entries · CC-BY 4.0

Outliers in R: Find, Flag and Remove Them (boxplot.stats, IQR, dplyr)

How to find and remove outliers in R with boxplot.stats(), IQR fences and dplyr, including the NA trap and when not to remove a point.

Written and maintained by CASRAI Editorial Board

Last updated

Finding an outlier in R and removing one are two separate decisions. Detection is a few lines of code: boxplot.stats(x)$out returns the values that fall beyond the whiskers. Removal is where analyses go wrong, because the filter you write can silently drop rows you never meant to touch, and because the statistical question, whether the point should go at all, comes first. This guide covers both, with code you can run on a small example, and shows where the common shortcuts disagree with each other.

What it is used for in research

NIST/SEMATECH defines an outlier as “an observation that lies an abnormal distance from other values in a random sample from a population.” In research data that usually means one of three things: a recording or entry error, a measurement from a different process than the rest of the sample, or a genuine extreme value. The NIST e-Handbook warns that outliers “should be investigated carefully,” that “often they contain valuable information about the process under investigation,” and that “before considering the possible elimination of these points from the data, one should try to understand why they appeared.” It adds, “of course, outliers are often bad data points.”

So the workflow in this guide is: detect, flag, investigate, then decide. For the statistics behind the rule, see how to find an outlier in statistics; for the plot itself, see box plots in R.

Install or access (official source only)

Everything in the detection section uses base R and the grDevices package that ships with it. The removal examples that use the pipe-friendly filter() need the dplyr package from CRAN:

install.packages("dplyr")
library(dplyr)

R itself is distributed from the Comprehensive R Archive Network at cran.r-project.org.

Step-by-step task: how to find an outlier in R

Use this small example throughout. It has 12 values and one that looks far from the rest.

df <- data.frame(
  id = 1:12,
  value = c(10, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 33)
)
  1. Look first. Run boxplot(df$value). Points drawn beyond the whiskers are the candidates.
  2. Extract the values the plot treats as outliers. out <- boxplot.stats(df$value)$out returns 33 here. According to the R manual, $out holds “the values of any data points which lie beyond the extremes of the whiskers.”
  3. Find the rows, not just the values. df[df$value %in% out, ] returns the full record, so you can check the id against your source data.
  4. Change the whisker length if you need to. The signature is boxplot.stats(x, coef = 1.5, do.conf = TRUE, do.out = TRUE), and coef “determines how far the plot ‘whiskers’ extend out from the box.” Setting coef = 3 gives a stricter, hinge-based version of the outer fence described next.

Mild and extreme outliers

The NIST handbook uses two pairs of fences. The inner fences sit at Q1 minus 1.5 times the interquartile range and Q3 plus 1.5 times the interquartile range; points beyond them are “mild outliers.” The outer fences use a multiplier of 3; points beyond them are “extreme outliers.” In boxplot.stats() terms, the default coef = 1.5 lists mild and extreme points together, and coef = 3 lists only the points beyond the wider fence.

Why two R methods can disagree

Many tutorials compute the fences by hand with quantile() or IQR() and treat the result as the same thing boxplot.stats() returns. They are close but not identical. The R manual says boxplot.stats() uses hinges, “versions of the first and third quartile,” and that the hinges equal the quartiles for odd n and differ for even n.

On the 12-value example above, the hinges are 13.5 and 20, giving fences of 3.75 and 29.75. The default quantile() quartiles are 13.75 and 19.5, giving fences of 5.125 and 28.125. Both flag 33 and nothing else here, but a value sitting between the two sets of fences would be flagged by one method and not the other. Pick one method, state it in your methods section, and use it for the whole dataset. The interquartile range in R guide covers the IQR() function and its type argument.

A z-score alternative

A second common approach standardizes the variable and flags values far from the mean:

z <- (df$value - mean(df$value)) / sd(df$value)
df[abs(z) > 3, ]

The cutoff of 3 is a convention you choose and report, not a property of the data. Because the mean and standard deviation are themselves pulled by the extreme value, a z-score can understate how unusual a single large point is in a small sample. For model-based checks on regression residuals, see standardized residuals.

How to remove an outlier in R

Remove only after you have a reason that is independent of the data being inconvenient, such as a confirmed entry error. Three patterns follow, from safest to most destructive.

1. Flag, do not delete

df$is_outlier <- df$value %in% out

A flag column keeps the original data intact, lets you run the analysis with and without the point, and makes the decision auditable.

2. Drop the flagged rows

df_clean <- df[!df$value %in% out, ]
# or, with dplyr
df_clean <- df |> filter(!value %in% out)

3. Filter on the fences

lo <- 5.125; hi <- 28.125   # from your own quartile calculation
df_clean <- df |> filter(value >= lo, value <= hi)

The missing-value trap. The dplyr documentation states that filter() keeps the rows where the condition is true and that it “drops both NA and FALSE.” A fence filter such as value >= lo, value <= hi therefore deletes every row where value is NA along with the outliers, so your row count falls by more than the number of outliers. Check with sum(is.na(df$value)) before and after, or use the %in% out pattern above, which leaves missing values in place.

Replace instead of remove

If deleting the point would bias the sample, the alternatives are to cap it (winsorizing) or to trim a fixed share of each tail. The trade-offs are covered in winsorizing vs trimming for outlier handling, and the effect on a summary statistic in the trimmed mean formula. For where outlier handling sits in a wider workflow, see data cleaning steps.

Output and how to read it

  • $stats is a vector of five numbers: the extreme of the lower whisker, the lower hinge, the median, the upper hinge, and the extreme of the upper whisker.
  • $out lists the points beyond the whiskers. An empty result (numeric(0)) means nothing falls outside the fences, not that the data are free of problems.
  • A flagged value is a prompt to investigate. NIST’s guidance is to understand why it appeared before eliminating it.

Troubleshooting

  • The row count dropped by more than the number of outliers. Missing values were removed by filter(); see the trap above.
  • Your hand-computed fences disagree with boxplot.stats(). Hinges and quantile() quartiles can differ for even sample sizes; use one method consistently.
  • New outliers appear after you remove the first. Quartiles change when rows are removed, so repeated rounds of removal will keep finding points. Decide on one pass and document it.

Alternatives for the same task

Approach What it does Source
boxplot.stats(x)$out Returns values beyond the whiskers, using hinges, with coef controlling whisker length R manual, grDevices
Fences from quantile() or IQR() Computes Q1 and Q3 minus/plus 1.5 times the interquartile range (3 for extreme outliers) NIST/SEMATECH e-Handbook
dplyr::filter() Subsets rows by condition; drops rows where the condition is NA or FALSE dplyr reference

FAQ

How to remove an outlier in R?

Identify the values with out <- boxplot.stats(df$value)$out, then drop those rows with df[!df$value %in% out, ] or filter(df, !value %in% out). Investigate the cause first, and keep a flag column or the original data so the step can be reversed.

How to find an outlier in R?

Run boxplot.stats(x)$out on a numeric vector, or plot it with boxplot(x) and read the points beyond the whiskers. Set coef = 3 to list only extreme outliers. See also box plots in R.

Should I remove outliers at all?

Not automatically. NIST notes that outliers often carry information about the process, and that you should understand why they appeared before eliminating them.

Sources (official docs)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Outliers in R: Find, Flag and Remove Them (boxplot.stats, IQR, dplyr)

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.