ggplot2::coord_flip
coord_flip swaps the x and y axes in a ggplot2 plot. The primary use case is displaying charts that are easier to read horizontally — long category labels, boxplots with many groups, or histograms with labeled x-axis text.
Signature
coord_flip(xlim = NULL, ylim = NULL, expand = TRUE, clip = "on")
Arguments:
xlim— limits for the x axis (before flip; after flip, this controls the vertical axis)ylim— limits for the y axis (before flip; after flip, this controls the horizontal axis)expand— ifTRUE(default), adds a small expansion factor so data and axes do not overlap. SetFALSEfor exact limits.clip— if"on"(default), drawing is clipped to the plot panel."off"allows points to appear outside the panel area.
Returns: A CoordFlip object.
Basic Usage
library(ggplot2)
# Vertical boxplot — fine, but x-axis labels may crowd
ggplot(diamonds, aes(cut, price)) +
geom_boxplot()
If cut has many levels or long labels, the x-axis gets cramped. coord_flip solves this:
# Horizontal boxplot — labels have room to breathe
ggplot(diamonds, aes(cut, price)) +
geom_boxplot() +
coord_flip()
How coord_flip Interacts with Scales
After a flip, the scale functions reverse too. scale_x_*() controls what was originally the y-axis (now the vertical axis), and scale_y_*() controls what was originally the x-axis (now the horizontal axis):
ggplot(diamonds, aes(cut, price)) +
geom_boxplot() +
coord_flip() +
scale_y_continuous(labels = scales::comma) # controls the horizontal axis after flip
When you reach for scale_x_*() expecting to style what looks like the horizontal axis, it is actually controlled by scale_y_*() after flipping. This is the most common gotcha.
Theme Elements Also Flip
Axis-related theme settings flip with the axes:
axis.line.xnow controls the horizontal rule (was vertical before flip)axis.text.ynow controls horizontal labels (was vertical before flip)
ggplot(diamonds, aes(cut, price)) +
geom_boxplot() +
coord_flip() +
theme(axis.text.y = element_text(size = 8)) # styles the horizontal tick labels
coord_flip vs Swapping Aesthetics
coord_flip is superseded in favor of simply swapping the x and y aesthetics directly. Both approaches work, but swapping avoids the axis and scale confusion:
# Old way: flip after writing vertical code
ggplot(diamonds, aes(cut, price)) +
geom_boxplot() +
coord_flip()
# Preferred modern approach: swap x and y in aes()
ggplot(diamonds, aes(price, cut)) +
geom_boxplot()
The direct swap is cleaner because scale_y_*() then correctly styles the y-axis without unexpected reversals. coord_flip remains useful for geoms and stats that do not support the orientation argument.
Common Use Cases
Horizontal Bar Charts
A bar chart with many categories is far easier to read horizontally:
library(dplyr)
diamonds %>%
count(cut) %>%
ggplot(aes(n, cut)) +
geom_col() +
coord_flip()
Grouped Boxplots with Many Groups
When you have a boxplot with a dozen or more groups on the x-axis, coord_flip gives the labels room to breathe:
ggplot(mpg, aes(class, hwy)) +
geom_boxplot() +
coord_flip()
Histograms with Overlapping Labels
If your histogram bins have string labels that overlap when stacked vertically, flip to horizontal:
ggplot(diamonds, aes(cut)) +
geom_histogram(stat = "count") +
coord_flip()
Facet Behavior
coord_flip does not change the facet order in facet_grid() or facet_wrap(). Facets continue to work as expected:
ggplot(diamonds, aes(cut, price)) +
geom_boxplot() +
coord_flip() +
facet_wrap(vars(clarity), ncol = 4)
What Does Not Change
After coord_flip, certain things behave counter-intuitively:
geom_vline()still draws a vertical line, but that line now appears horizontally because the coordinate system is flippedannotation_logticks()may need adjustment because tick marks follow the flipped axes- Position adjustments like
position_dodge()continue to dodge along the correct axis, but the visual result is rotated
See Also
- /reference/tidyverse/ggplot2_aes/ — aesthetic mappings
- /reference/tidyverse/ggplot2_theme/ — theme customization
- /tutorials/r-data-visualization/ggplot2-basics/ — ggplot2 fundamentals