Use facet_wrap in R (With Examples)


Data visualization is an indispensable practice within Exploratory Data Analysis (EDA), particularly when working with complex, multivariate datasets in R. A common challenge arises when a single plot becomes cluttered by multiple subgroups, obscuring meaningful patterns. To overcome this, analysts employ a powerful technique known as conditioning, which involves breaking down a primary visualization into a series of smaller, comparative subplots based on a categorical variable. This process is handled exceptionally well within the popular ggplot2 package using the specialized function, facet_wrap().

The core purpose of the facet_wrap() function is to generate “small multiples”—a series of plots identical in structure but unique in the subset of data they display. By arranging these plots into a compact, tiled layout, viewers can effortlessly compare distributions, trends, or correlations across different levels of a chosen factor variable. This approach moves the analysis beyond simple bivariate relationships toward sophisticated conditional analysis, dramatically enhancing the clarity and interpretability of your findings, which is paramount for effective data communication.

To successfully implement multi-panel plotting using facet_wrap(), the first step involves defining your base plot. This includes specifying the data source, mapping the appropriate aesthetics (such as X and Y variables), and selecting the necessary geometric layers (like points or bars). The crucial faceting layer is then appended using the standard ggplot2 syntax. The categorical variable that dictates the creation of the individual panels must be enclosed within the vars() helper function, as demonstrated in the foundational code structure below:

library(ggplot2)

ggplot(df, aes(x_var, y_var)) +
  geom_point() +
  facet_wrap(vars(category_var))

For all subsequent examples and demonstrations throughout this guide, we will leverage the globally available mpg dataset. This dataset is a standard inclusion within the ggplot2 package ecosystem and contains comprehensive fuel economy data meticulously collected by the US Environmental Protection Agency, covering 38 popular car models. This rich, real-world data provides an excellent foundation for illustrating how faceting works in practice.

A prerequisite for effective visualization is a thorough understanding of the underlying data structure. Before we proceed to create multi-panel plots, it is helpful to preview the contents of the mpg dataset. The snapshot below shows the first six rows, highlighting key variables such as displ (engine displacement in liters), hwy (highway miles per gallon), and class (the vehicle type classification, which will serve as our primary faceting variable):

#view first six rows of mpg dataset
head(mpg)

manufacturer  model  displ  year  cyl	     trans  drv	cty  hwy  fl	  class
										
audi	         a4    1.8  1999    4	auto(l5)      f	18    29   p	compact
audi	         a4    1.8  1999    4	manual(m5)    f	21    29   p	compact
audi	         a4    2.0  2008    4	manual(m6)    f	20    31   p	compact
audi	         a4    2.0  2008    4	auto(av)      f	21    30   p	compact
audi	         a4    2.8  1999    6	auto(l5)      f	16    26   p	compact
audi	         a4    2.8  1999    6	manual(m5)    f	18    26   p	compact

Example 1: Implementing the Basic facet_wrap() Function

The most common and fundamental application of facet_wrap() involves visualizing the interaction between two continuous variables across every level of a specified categorical variable. In this initial demonstration, our objective is to analyze the relationship between vehicle engine displacement (displ) and highway fuel efficiency (hwy), while simultaneously conditioning this view based on the vehicle type (class).

The following code executes this exact visualization goal. It instructs R to generate a distinct scatterplot for every unique value present in the class column. Crucially, the facet_wrap() function takes responsibility for automatically arranging these individual plots into an optimized, compact multi-panel display. This automatic tiling ensures that the visual comparison across disparate vehicle types—such as SUVs versus subcompacts—is immediate and highly effective.

ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  facet_wrap(vars(class))

By separating the data into conditional views, the resulting visualization sharply delineates the data points for each vehicle category. This isolation allows the user to quickly discern distinct performance trends. For instance, one can readily observe the correlation between generally lower engine displacement and superior mileage in categories like compact or subcompact vehicles, contrasting starkly with the higher displacement and lower mileage typical of suv or pickup trucks.

Example 2: Applying Custom Labels for Enhanced Clarity

When preparing visualizations for professional reports or public consumption, the default facet labels generated by ggplot2 often utilize the raw, short-hand values from the dataset (e.g., suv, 2seater). These cryptic identifiers can confuse an unfamiliar audience. Therefore, it is a critical step in refining a visualization to replace these factor levels with descriptive, human-readable titles. This essential task is accomplished by defining a named vector of custom labels and then passing this vector to the labeller argument within the facet_wrap() function call.

The process begins with the creation of a mapping object, which we name plot_names. Within this object, the original factor level serves as the key, and the corresponding desired descriptive plot title serves as the value. Subsequently, the as_labeller() function is used to correctly interpret and apply this comprehensive mapping to the facet titles during the plot rendering process. This ensures a consistent and meaningful translation from data shorthand to clear visual communication.

#define custom labels
plot_names <- c('2seater' = "2 Seater",
                'compact' = "Compact Vehicle",
                'midsize' = "Midsize Vehicle",
                'minivan' = "Minivan",
                'pickup' = "Pickup Truck",
                'subcompact' = "Subcompact Vehicle",
                'suv' = "Sport Utility Vehicle")

#use facet_wrap with custom plot labels
ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  facet_wrap(vars(class), labeller = as_labeller(plot_names))

Implementing custom labels is more than just an aesthetic improvement; it is a fundamental step in ensuring that the audience immediately grasps the context and content of each subplot. This technique significantly elevates the overall accessibility, professionalism, and narrative coherence of the final data visualization, making the results instantly understandable regardless of the viewer’s familiarity with the raw dataset.

facet_wrap with custom labels in R

Example 3: Controlling Axes with Custom Scales

A key characteristic of facet_wrap() by default is the use of fixed scales. This means that all generated subplots share identical X and Y axis limits, determined by the minimum and maximum values across the entire dataset. While this feature is absolutely essential for accurate visual comparison and judging the relative magnitude of groups, it can occasionally hide important variations within smaller panels if their data range is minute compared to the overall dataset spread.

To mitigate this potential issue, analysts can modify the axis behavior by setting the optional scales argument to the value 'free'. When this parameter is activated, R and the ggplot2 package are instructed to dynamically adjust the X and Y axes independently for every panel. The limits of each panel’s axes are determined solely by the data points present within that specific facet. Additional options include 'free_x' (adjusting only the X-axis) or 'free_y' (adjusting only the Y-axis).

#use facet_wrap with custom scales
ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  facet_wrap(vars(class), scales='free')

The strategic use of free scales permits a much closer and more detailed examination of the internal structure, density, and specific local trends within the data points of each subgroup. However, users must proceed with caution: while local detail is enhanced, implementing free scales inherently removes the ability to visually judge the relative scale and magnitude of values across the different panels, potentially hindering overall cross-group comparison.

Example 4: Defining a Custom Panel Order

By default, the layout order of panels generated by facet_wrap() is dictated strictly by the alphanumeric sorting of the factor levels within the underlying variable. Yet, effective and persuasive data visualization often demands that information be presented in a specific, logically coherent sequence—perhaps ordered by magnitude, hierarchical importance, or chronological progression, rather than alphabetical sorting.

To successfully impose a custom ordering on the facets, a necessary preparatory step must be executed before calling the plotting function. We must explicitly convert the faceting variable (which is class in our example) into an ordered factor variable. This conversion is performed using the factor() function, where the exact desired sequence of levels is defined using the levels argument. This ensures that the R environment recognizes and respects the desired display order.

#define order for plots
mpg <- within(mpg, class <- factor(class, levels=c('compact', '2seater', 'suv',
                                                   'subcompact', 'pickup',
                                                   'minivan', 'midsize')))

#use facet_wrap with custom order
ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  facet_wrap(vars(class))

As clearly illustrated in the resulting visualization, the physical layout of the panels now rigorously adheres to the custom level ordering defined within the factor function. The display sequence begins with compact and proceeds exactly as specified in the factor levels definition. Gaining this level of control over the visual presentation is invaluable for guiding the viewer through complex comparative narratives and maximizing the plot’s impact.

face_wrap() with custom order in R

The panels are now displayed in the exact order that was programmatically specified, demonstrating the successful enforcement of the custom factor levels.

Further Exploration of Faceting Techniques

The facet_wrap() function is an incredibly powerful tool, celebrated for its ability to simplify the generation of numerous comparative plots from a single, streamlined command. While this guide has centered on faceting by a single categorical variable, the ggplot2 package suite offers additional versatility. Specifically, the related function, facet_grid(), is designed for faceting based on two independent variables simultaneously, allowing for the creation of a structured matrix of plots (e.g., separating rows by one variable and columns by another).

For analysts dedicated to mastering advanced conditional visualization techniques in R, we strongly recommend a deeper dive into the official documentation. This material covers additional fine-tuning parameters for facet_wrap(), such as nrow and ncol for explicit layout dimension control, and dir for specifying the direction in which the facets should wrap (e.g., horizontally or vertically). These tools provide complete mastery over the final presentation of your small multiples.

Throughout this tutorial, we have successfully covered several fundamental and advanced concepts necessary for effective conditional visualization:

  • The basic structural requirements for generating efficient multi-panel plots.
  • The utilization of the labeller argument for professional clarification of plot titles.
  • Methods for adjusting axis limits using the scales argument to highlight internal group variation.
  • The crucial technique of controlling panel display order through manipulation of factor levels.

Additional Resources

For more detailed information, source code, and comprehensive guidance on faceting and conditional plotting in R:

Cite this article

Mohammed looti (2025). Use facet_wrap in R (With Examples). PSYCHOLOGICAL STATISTICS. Retrieved from https://statistics.arabpsychology.com/use-facet_wrap-in-r-with-examples/

Mohammed looti. "Use facet_wrap in R (With Examples)." PSYCHOLOGICAL STATISTICS, 4 Nov. 2025, https://statistics.arabpsychology.com/use-facet_wrap-in-r-with-examples/.

Mohammed looti. "Use facet_wrap in R (With Examples)." PSYCHOLOGICAL STATISTICS, 2025. https://statistics.arabpsychology.com/use-facet_wrap-in-r-with-examples/.

Mohammed looti (2025) 'Use facet_wrap in R (With Examples)', PSYCHOLOGICAL STATISTICS. Available at: https://statistics.arabpsychology.com/use-facet_wrap-in-r-with-examples/.

[1] Mohammed looti, "Use facet_wrap in R (With Examples)," PSYCHOLOGICAL STATISTICS, vol. X, no. Y, ص Z-Z, November, 2025.

Mohammed looti. Use facet_wrap in R (With Examples). PSYCHOLOGICAL STATISTICS. 2025;vol(issue):pages.

Download Post (.PDF)
Scroll to Top