Labeling Outliers in Boxplots using ggplot2: A Step-by-Step Guide


This comprehensive tutorial serves as an essential guide for data analysts and statisticians looking to enhance their visualizations. We will walk through the precise steps required to label outliers within boxplots, leveraging the visualization capabilities of the powerful ggplot2 package in R. Effectively identifying and annotating outliers is not merely a cosmetic choice; it is a critical step in rigorous data analysis. These unusual observations can disproportionately influence statistical findings, skew model predictions, and highlight genuine anomalies or errors in data collection. By clearly marking them on your plots, you provide immediate, actionable insight into the data’s distribution and structure.

Our focus will be on creating a reusable workflow that combines data manipulation using the dplyr package with the graphical precision of ggplot2. This method ensures that the process of outlier detection is performed correctly—independently for each group—and that the resulting labels are informative, whether they display the numerical value of the anomaly or the specific identifier associated with it.

Step 1: Preparing the Sample Data Frame in R

To demonstrate the labeling process accurately, we must first establish a representative dataset containing potential outliers. For this example, we will simulate a data frame that records the points scored by 60 hypothetical basketball players distributed across three distinct teams (A, B, and C). This structure allows us to generate a realistic scenario where distributions vary between groups, making group-specific outlier detection necessary.

# Ensure consistency in random data generation
set.seed(1)

# Create the data frame structure
df <- data.frame(team=rep(c('A', 'B', 'C'), each=20),
                 player=rep(LETTERS[1:20], times=3),
                 points=round(rnorm(n=60, mean=30, sd=10), 2))

# Display the initial structure of the data
head(df)

  team player points
1    A      A  23.74
2    A      B  31.84
3    A      C  21.64
4    A      D  45.95
5    A      E  33.30
6    A      F  21.80

The use of the set.seed() function at the beginning of the script is paramount for ensuring reproducibility. By fixing the seed, anyone running this code will generate the exact same random point scores, making the identification of outliers consistent. Following this, the data.frame() function constructs our dataset, assigning players to teams and generating scores centered around a mean of 30 with a standard deviation of 10. The output of head(df) confirms the successful creation and initial structure of the dataset.

Step 2: Defining the Statistical Logic for Outlier Detection

Before we can visually label observations, we must first programmatically determine which data points qualify as outliers according to established statistical definitions used in boxplots. By convention, an observation is typically defined as an outlier if it extends significantly beyond the main body of the data, quantified using the interquartile range (IQR).

The standard criteria classify a data point as an outlier if its value falls outside the fences defined by 1.5 times the Interquartile Range (IQR). Specifically, these two conditions must be evaluated:

  1. The observation is less than the first quartile (Q1) minus 1.5 times the IQR.
  2. The observation is greater than the third quartile (Q3) plus 1.5 times the IQR.

To implement this logic efficiently in R, we create a specialized custom function, find_outlier. This function takes a numeric vector (like our ‘points’ column) and returns a logical vector (TRUE/FALSE), indicating precisely which elements satisfy the outlier criteria. This modular approach allows for easy application across different variables in various datasets.

find_outlier <- function(x) {
  return(x < quantile(x, .25) - 1.5*IQR(x) | x > quantile(x, .75) + 1.5*IQR(x))
}

Inside the find_outlier function, we rely on R’s core statistical functions: quantile() calculates the 25th percentile (Q1) and 75th percentile (Q3), while IQR() computes the interquartile range (Q3 – Q1). The logical OR operator (|) ensures that any observation meeting either the lower boundary condition or the upper boundary condition is flagged as an outlier, thereby streamlining the detection process.

Step 3: Labeling Outliers with Numerical Values using ggplot2

With the data prepared and the outlier detection mechanism established, the next phase involves integrating this information into our ggplot2 visualization. This step requires careful data manipulation using dplyr to create a designated labeling column before plotting the results.

library(ggplot2)
library(dplyr)

# Create a new column 'outlier' containing only the point values of outliers
df <- df %>%
        group_by(team) %>%
        mutate(outlier = ifelse(find_outlier(points), points, NA))

# Generate the box plot and apply numerical labels
ggplot(df, aes(x=team, y=points)) +
  geom_boxplot() +
  geom_text(aes(label=outlier), na.rm=TRUE, hjust=-.5)

The data preparation is handled by chaining operations using the pipe operator (%>%). Critically, we use group_by(team) to partition the data, ensuring that the outlier criteria (Q1, Q3, and IQR) are calculated independently for each team. This prevents points from a high-scoring team from masking genuine outliers in a low-scoring team, or vice versa. The subsequent mutate() call creates the new outlier column. The ifelse() function conditionally populates this column: if find_outlier(points) is TRUE, the actual points value is assigned; otherwise, NA (Not Applicable) is used.

In the plotting stage, ggplot() initializes the visual space. geom_boxplot() draws the core boxplot layers. The labeling magic occurs with geom_text(). By mapping the aesthetic label=outlier, ggplot2 is instructed to use the contents of our newly created column for text annotation. Because we set non-outliers to NA, and use the na.rm=TRUE argument, only the actual outlier values are plotted. The hjust=-.5 parameter slightly nudges the text horizontally to the right, guaranteeing that the numerical label does not obscure the geometric point representing the observation.

label outliers in boxplots in ggplot2

The resulting visualization clearly marks and labels the two identified outliers. We can instantly determine that the anomalous score for Team A is 7.85 points, and the corresponding anomalous score for Team B is 10.11 points. This numerical annotation provides immediate quantitative context for these extreme observations.

Step 4: Labeling Outliers with Descriptive Identifiers (Player Name)

While numerical labels are precise, they often lack contextual meaning. In analytical contexts, it is frequently more beneficial to identify the specific entity responsible for the anomalous data point—in our case, the player’s name—rather than just the score itself. This modification is straightforward, requiring only a small adjustment to the data manipulation step implemented in Step 3.

To achieve this, we simply modify the mutate() function to conditionally store the descriptive identifier (the player name) instead of the numerical measure (the points score) when the outlier condition is met. The remainder of the plotting code remains identical, as it relies solely on the content of the outlier column for labeling.

library(ggplot2)
library(dplyr)

# Add new column that stores the PLAYER name if the observation is an outlier
df <- df %>%
        group_by(team) %>%
        mutate(outlier = ifelse(find_outlier(points), player, NA))

# Create box plot of points by team and label outliers with player names
ggplot(df, aes(x=team, y=points)) +
  geom_boxplot() +
  geom_text(aes(label=outlier), na.rm=TRUE, hjust=-.5)

By changing the assignment within the mutate() function from points to player, we switch the content of the labels from quantitative scores to qualitative identifiers. This is a powerful demonstration of how flexible data preparation can be combined with static visualization layers in ggplot2 to significantly improve interpretability.

The updated boxplot now clearly shows that the outlier on Team A is associated with the player labeled ‘N’, and the outlier on Team B corresponds to player ‘D’. This method provides immediate context, allowing analysts to quickly follow up on why these specific individuals recorded unusually low scores compared to their teammates.

A final technical consideration is the role of the hjust argument in geom_text(). Setting hjust=-.5 applies a horizontal justification offset, moving the text label slightly away from the data point. This minor visual adjustment is essential for producing professional, high-quality visualizations where text elements do not overlap with data markers, thereby maintaining graphical clarity and readability across all data distributions.

Additional Resources for Advanced Visualization

Mastering the labeling of outliers represents a significant step in producing informative and polished visualizations. To further advance your skills in data analysis and graphical presentation using R, we recommend exploring the following authoritative resources and related tutorials:

  • Official ggplot2 Documentation: Essential reading for deeper understanding of the grammar of graphics and customization options.
  • dplyr Package Documentation: Focus on data transformation verbs (like group_by() and mutate()) to prepare data for visualization efficiently.
  • Understanding Boxplots: Review the statistical theory behind boxplots, quartiles, and the definition of fences.
  • Interquartile Range and Data Spread: Explore statistical concepts like the Interquartile Range (IQR) to refine your knowledge of robust measures of variability.

Cite this article

Mohammed looti (2025). Labeling Outliers in Boxplots using ggplot2: A Step-by-Step Guide. PSYCHOLOGICAL STATISTICS. Retrieved from https://statistics.arabpsychology.com/label-outliers-in-boxplots-in-ggplot2/

Mohammed looti. "Labeling Outliers in Boxplots using ggplot2: A Step-by-Step Guide." PSYCHOLOGICAL STATISTICS, 28 Oct. 2025, https://statistics.arabpsychology.com/label-outliers-in-boxplots-in-ggplot2/.

Mohammed looti. "Labeling Outliers in Boxplots using ggplot2: A Step-by-Step Guide." PSYCHOLOGICAL STATISTICS, 2025. https://statistics.arabpsychology.com/label-outliers-in-boxplots-in-ggplot2/.

Mohammed looti (2025) 'Labeling Outliers in Boxplots using ggplot2: A Step-by-Step Guide', PSYCHOLOGICAL STATISTICS. Available at: https://statistics.arabpsychology.com/label-outliers-in-boxplots-in-ggplot2/.

[1] Mohammed looti, "Labeling Outliers in Boxplots using ggplot2: A Step-by-Step Guide," PSYCHOLOGICAL STATISTICS, vol. X, no. Y, ص Z-Z, October, 2025.

Mohammed looti. Labeling Outliers in Boxplots using ggplot2: A Step-by-Step Guide. PSYCHOLOGICAL STATISTICS. 2025;vol(issue):pages.

Download Post (.PDF)
Scroll to Top