Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

Axis in R: Titles, Limits, Breaks and Labels in Base R and ggplot2

How to set axis titles, limits, breaks, labels and log scales in R, and when ggplot2 limits drop data while coord_cartesian only zooms.

Written and maintained by CASRAI Editorial Board

Last updated

An axis in R is the scale along the bottom or side of a plot: its title, its range, where the tick marks sit and what they are labelled. R has two common ways to draw plots, base R graphics (plot(), axis()) and the ggplot2 package (scale_x_continuous(), coord_cartesian()). Both let you set a title, limits, breaks and labels; they differ in what happens to data that falls outside the limits, which is the most common source of confusing results.

What it is used for in research

Axes decide how a reader judges a figure. A research figure usually needs a title that names the variable and its unit, a range that shows all of the data (or a clearly labelled zoom), tick marks at meaningful values, and sometimes a logarithmic scale for values that span orders of magnitude. For wider figure practice, see the guide on building, styling and saving plots with ggplot2; this page covers the axis itself.

Install or access

Base R graphics ship with R, so plot() and axis() need no extra installation. The ggplot2 functions come from the ggplot2 package, installed from CRAN once and loaded in each session:

install.packages("ggplot2")
library(ggplot2)

The function arguments below follow the R graphics manual and the ggplot2 reference site, both listed under Sources.

Step-by-step: set the axis title, limits, breaks and labels

The examples use mtcars, a data set included with R.

  1. Set the axis titles. In base R, pass xlab and ylab to plot(); the R manual says each is a label for the axis and defaults to a description of the plotted data. In ggplot2, the name argument of a scale is “used as the axis or legend title”.
    # base R
    plot(mtcars$wt, mtcars$mpg, xlab = "Weight (1000 lb)", ylab = "Miles per gallon")
    
    # ggplot2
    ggplot(mtcars, aes(wt, mpg)) + geom_point() +
      scale_x_continuous(name = "Weight (1000 lb)") +
      scale_y_continuous(name = "Miles per gallon")
  2. Set the limits. In base R, xlim and ylim are the limits (x1, x2) of the plot, and the manual notes that x1 > x2 is allowed and gives a reversed axis. In ggplot2, limits is “a numeric vector of length two”, with NA standing for the existing minimum or maximum; xlim() and ylim() are shortcuts.
    # base R
    plot(mtcars$wt, mtcars$mpg, xlim = c(0, 6), ylim = c(0, 40))
    
    # ggplot2
    ggplot(mtcars, aes(wt, mpg)) + geom_point() +
      scale_x_continuous(limits = c(0, 6)) +
      scale_y_continuous(limits = c(0, NA))

    See the decision table in the next section before using ggplot2 limits on a plot that also draws a summary layer.

  3. Set the breaks and labels. In ggplot2, breaks sets the tick positions and labels is “a character vector giving labels (must be same length as breaks)”; n.breaks asks for an approximate number of ticks instead. In base R, axis() takes at (tick positions) and labels.
    # ggplot2
    ggplot(mtcars, aes(wt, mpg)) + geom_point() +
      scale_x_continuous(breaks = c(2, 3, 4, 5), labels = c("two", "three", "four", "five"))
  4. Use a logarithmic scale. In base R, log = "x", "y" or "xy" in plot() makes the named axes logarithmic. In ggplot2, scale_x_log10() and scale_y_log10() pass their arguments to scale_(x|y)_continuous() and set the transformation. The continuous scales take the transformation in transform; the older trans argument is deprecated.
    # base R
    plot(mtcars$disp, mtcars$mpg, log = "x")
    
    # ggplot2
    ggplot(mtcars, aes(disp, mpg)) + geom_point() + scale_x_log10()
  5. Hide or replace a base R axis. The graphical parameters xaxt (sides 1 and 3) and yaxt (sides 2 and 4) control whether an axis is drawn at all. Set xaxt = "n", then add your own axis with axis(side, at, labels), where side is 1 = below, 2 = left, 3 = above and 4 = right.
    plot(mtcars$wt, mtcars$mpg, xaxt = "n")
    axis(1, at = c(2, 3, 4, 5), labels = c("two", "three", "four", "five"))

    If labels is not logical, supply at with the same length. The orientation of tick labels is controlled by las.

Output and how to read it

In ggplot2 there are two different ways to change the visible range, and they do not do the same thing to your data.

Method What the documentation says Effect on the data
limits in a scale, xlim(), ylim(), lims() “Setting limits on positional scales will remove data outside of the limits”; by default values outside the limits are replaced with NA Data outside the range is discarded. The documentation warns this “can produce unintended results”.
oob = scales::squish in a scale The default oob is scales::censor(), which replaces out-of-bounds values with NA; scales::squish() squishes them into the range Out-of-range values are kept and pulled to the edge of the range instead of becoming NA.
coord_cartesian(xlim, ylim) “Setting limits on the coordinate system will zoom the plot” and “will not change the underlying data like setting limits on a scale will” A visual zoom; the data is unchanged.

The ggplot2 documentation recommends coord_cartesian() to change the limits without dropping data observations. Its expand = TRUE default adds a small expansion so data and axes do not overlap; scale limits likewise expand by 5% on each side for continuous variables by default, and expand in the scale changes that.

ggplot(mtcars, aes(wt, mpg)) + geom_point() +
  coord_cartesian(xlim = c(2, 4), ylim = c(15, 30))

To read a plot with a changed axis, check three things: the axis title (does it name the variable and unit), the limits (are any observations outside them), and whether the scale is linear or logarithmic, because equal distances on a log axis are equal ratios, not equal differences.

Troubleshooting

Points or bars disappear after setting limits in ggplot2

Scale limits remove data outside the range (replaced with NA by default). If you only want to look at part of the plot, use coord_cartesian() instead; if you want to keep out-of-range values at the edge, set oob = scales::squish in the scale.

Labels and breaks do not match

In scale_x_continuous() and scale_y_continuous(), labels must be the same length as breaks. Supply both with equal lengths, or leave labels unset.

The axis is missing in base R

Check whether xaxt = "n" or yaxt = "n" is set, or axes = FALSE. The R manual states that axes controls both axes, and that xaxt or yaxt suppress just one.

The log scale warns about values

A logarithmic axis cannot show values of zero or below. The R manual’s own example shows plot(y ~ x, log = "x") giving a warning that x values less than or equal to zero are omitted.

An old script uses trans

The trans argument of the continuous scales is deprecated in favour of transform.

Free alternatives

Base R graphics and ggplot2 are the two approaches covered above. Which task maps to which argument:

Task Base R ggplot2
Axis title xlab, ylab in plot() name in scale_x_continuous() / scale_y_continuous()
Limits xlim, ylim in plot() limits in the scale, xlim() / ylim(), or coord_cartesian() to zoom
Tick positions and labels axis(side, at, labels) breaks and labels in the scale
Log scale log = "x", "y" or "xy" scale_x_log10(), scale_y_log10(), or transform

For the look of the axis (text size, lines, grid), see ggplot themes. Axis choices also matter for specific plot types: plotting a line in R, barplot in R and histograms in R.

FAQ

What is an axis in R?

It is the labelled scale along one side of a plot. In base R graphics it is drawn by plot() or axis(); in ggplot2 it is controlled by the x and y scales, such as scale_x_continuous().

How do I change the axis limits in R?

In base R, pass xlim and ylim to plot(). In ggplot2, use limits in a scale or xlim() / ylim() to remove data outside the range, or coord_cartesian(xlim, ylim) to zoom without removing data.

How do I change the axis labels in R?

Use xlab and ylab in base R, or name in the ggplot2 scale for the axis title; use labels (with matching breaks) for the tick labels.

How do I remove an axis in base R?

Set xaxt = "n" or yaxt = "n" in plot(); use axes = FALSE to remove both.

Sources

All pages checked on 2026-10-29.

Follow CASRAI

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

Ask CASRAI · free to try

Ask about Axis in R: Titles, Limits, Breaks and Labels in Base R and ggplot2

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 →