Base R Graphics and Plotting

· 4 min read · Updated March 11, 2026 · beginner
r graphics plotting data-viz base-r

R’s base graphics system gives you a powerful toolkit for creating plots without needing external packages. The graphics engine has been refined over decades, making it reliable and flexible. This guide walks through the most useful plotting functions and shows how to customize your output.

The plot() Function

The workhorse of base R graphics is plot(). It is a generic function that adapts its behavior based on the data type you provide.

# Simple scatter plot
x <- 1:10
y <- c(2, 4, 3, 7, 6, 9, 8, 12, 11, 15)
plot(x, y)

The function automatically chooses sensible defaults: point type, axis labels, and margins. You can override these:

plot(x, y, 
     main = "My First Plot",
     xlab = "X Axis Label",
     ylab = "Y Axis Label",
     col = "steelblue",
     pch = 19,
     cex = 1.5)

Key parameters:

  • main — plot title
  • xlab, ylab — axis labels
  • col — color (use hex codes or named colors)
  • pch — point type (1-25, where 19 is filled circles)
  • cex — size multiplier

You can also plot directly from a data frame:

plot(mtcars$wt, mtcars$mpg,
     xlab = "Weight (1000 lbs)",
     ylab = "Miles per Gallon",
     main = "Car Weight vs. Fuel Efficiency")

Line Plots

Connect points with lines using type = "l":

# Time series data
time <- 1:20
values <- cumsum(rnorm(20))

plot(time, values, 
     type = "l",
     col = "darkred",
     lwd = 2)

Use type = "b" for both points and lines:

plot(time, values,
     type = "b",
     pch = 16,
     col = "darkred")

Histograms with hist()

Histograms show the distribution of a continuous variable:

# Simple histogram
hist(mtcars$mpg)

# More control
hist(mtcars$mpg,
     breaks = 10,
     col = "steelblue",
     border = "white",
     main = "Distribution of MPG",
     xlab = "Miles per Gallon")

The breaks argument controls the number of bins. R chooses a sensible default, but you can fine-tune it.

Bar Charts with barplot()

Bar charts display categorical data:

# Simple bar chart
categories <- c("A", "B", "C", "D")
values <- c(23, 45, 32, 58)

barplot(values, 
        names.arg = categories,
        col = c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728"),
        main = "Sales by Category")

For stacked or grouped bars, use a matrix:

# Grouped bar chart
data_matrix <- matrix(c(10, 20, 15, 25, 12, 18), nrow = 2, ncol = 3)
barplot(data_matrix,
        beside = TRUE,
        names.arg = c("Q1", "Q2", "Q3"),
        col = c("steelblue", "coral"))

Box Plots with boxplot()

Box plots show distribution summary:

# Single box plot
boxplot(mtcars$mpg,
        main = "MPG Distribution")

# Box plot by group
boxplot(mpg ~ cyl, data = mtcars,
        main = "MPG by Cylinder Count",
        xlab = "Cylinders",
        ylab = "Miles per Gallon",
        col = "lightgray")

The box shows the interquartile range (IQR), the line inside is the median, and whiskers extend to 1.5 × IQR. Points beyond are shown individually.

Adding Elements to Plots

After creating a base plot, you can add more elements:

# Start with a plot
plot(x, y, type = "n")  # type = "n" creates empty plot

# Add points
points(x, y, col = "steelblue", pch = 16)

# Add a regression line
abline(lm(y ~ x), col = "red", lwd = 2)

# Add a horizontal line
abline(h = mean(y), col = "gray50", lty = 2)

# Add a vertical line
abline(v = 5, col = "green", lty = 3)

# Add text
text(x = 3, y = 14, labels = "Important Point", pos = 4)

# Add a legend
legend("topleft", legend = c("Data", "Trend"),
       col = c("steelblue", "red"), pch = c(16, NA), lty = c(NA, 1))

Saving Plots

Export your plots in various formats:

# Save as PNG
png("myplot.png", width = 800, height = 600)
plot(x, y)
dev.off()

# Save as PDF
pdf("myplot.pdf")
plot(x, y)
dev.off()

# Save as JPEG
jpeg("myplot.jpg", quality = 90)
plot(x, y)
dev.off()

Always call dev.off() to close the graphics device and complete the file.

Multiple Plots

Create multi-panel figures:

# 2x2 layout
par(mfrow = c(2, 2))

plot(x, y)
hist(mtcars$mpg)
boxplot(mtcars$mpg ~ mtcars$cyl)
barplot(values, names.arg = categories)

Reset the layout:

par(mfrow = c(1, 1))

Plot Parameters with par()

The par() function controls global graphics settings:

# Save current settings
old_par <- par(no.readonly = TRUE)

# Change settings
par(mar = c(5, 4, 2, 2),  # margins (bottom, left, top, right)
    mgp = c(3, 1, 0),     # axis positions
    cex.axis = 0.8)       # axis text size

# Your plots here

# Restore
par(old_par)

Useful parameters:

  • mar — margin sizes in lines
  • mfrow — number of rows and columns for multiple plots
  • oma — outer margin size
  • bg — background color
  • cex.main, cex.lab, cex.axis — text size multipliers

See Also

  • ggplot2 — the tidyverse plotting package for more complex visualizations
  • Interactive Plots with plotly — an alternative grid-based plotting system
  • graphics — the underlying graphics package documentation