Styles in Base R - Mastering Graphical Parameters with par()

The par() function in R is a powerful tool for fine-tuning the graphical output of your plots. Whether you’re tweaking the margins, setting up multi-figure layouts, or adjusting text properties, par() gives you control over the aesthetics of your graphics, enabling you to create clear and engaging visualizations.

Introduction

In R, visualization is a key part of the data analysis process. The par() function stands for “parameters” and is used to set or query graphical parameters, having far-reaching effects on how plots are rendered in R.

Basic Usage of par()

par() can be used in two main ways: querying the current graphical parameters and setting new parameter values. Let’s look at both uses.

Querying Graphical Parameters

To see all the current graphical parameters, just call par() without any arguments:

current_par <- par()
current_par
$xlog
[1] FALSE

$ylog
[1] FALSE

$adj
[1] 0.5

$ann
[1] TRUE

$ask
[1] FALSE

$bg
[1] "white"

$bty
[1] "o"

$cex
[1] 1

$cex.axis
[1] 1

$cex.lab
[1] 1

$cex.main
[1] 1.2

$cex.sub
[1] 1

$cin
[1] 0.15 0.20

$col
[1] "black"

$col.axis
[1] "black"

$col.lab
[1] "black"

$col.main
[1] "black"

$col.sub
[1] "black"

$cra
[1] 180 240

$crt
[1] 0

$csi
[1] 0.2

$cxy
[1] 0.02604167 0.06329114

$din
[1] 7 5

$err
[1] 0

$family
[1] ""

$fg
[1] "black"

$fig
[1] 0 1 0 1

$fin
[1] 7 5

$font
[1] 1

$font.axis
[1] 1

$font.lab
[1] 1

$font.main
[1] 2

$font.sub
[1] 1

$lab
[1] 5 5 7

$las
[1] 0

$lend
[1] "round"

$lheight
[1] 1

$ljoin
[1] "round"

$lmitre
[1] 10

$lty
[1] "solid"

$lwd
[1] 1

$mai
[1] 1.02 0.82 0.82 0.42

$mar
[1] 5.1 4.1 4.1 2.1

$mex
[1] 1

$mfcol
[1] 1 1

$mfg
[1] 1 1 1 1

$mfrow
[1] 1 1

$mgp
[1] 3 1 0

$mkh
[1] 0.001

$new
[1] FALSE

$oma
[1] 0 0 0 0

$omd
[1] 0 1 0 1

$omi
[1] 0 0 0 0

$page
[1] TRUE

$pch
[1] 1

$pin
[1] 5.76 3.16

$plt
[1] 0.1171429 0.9400000 0.2040000 0.8360000

$ps
[1] 12

$pty
[1] "m"

$smo
[1] 1

$srt
[1] 0

$tck
[1] NA

$tcl
[1] -0.5

$usr
[1] 0 1 0 1

$xaxp
[1] 0 1 5

$xaxs
[1] "r"

$xaxt
[1] "s"

$xpd
[1] FALSE

$yaxp
[1] 0 1 5

$yaxs
[1] "r"

$yaxt
[1] "s"

$ylbias
[1] 0.2

This will return a list of all the graphical parameters and their current settings. If you want to access a specific item, us the $` symbol. For example:

par()$ylbias
[1] 0.2

Setting Graphical Parameters

To set graphical parameters, you pass them as arguments to par(). For instance, to set the margins of a plot, you can use the mar parameter, which takes a numeric vector of four values representing the number of lines for the bottom, left, top, and right margins:

par(mar=c(5.1, 4.1, 4.1, 2.1))

Understanding Margins in R

To show how margins work, let’s use some previous data:

# Load necessary libraries

library(here)

weo_usa<-readRDS(here("databases/weo_usa.rds"))

First, we make a chart where the labels of the x and y-axis are on one line using data from 1980 onwards.

weo_usa <- subset(weo_usa, year >= 1980)
plot(weo_usa$lur,weo_usa$pcpi_pch,main="US: Unemployment and inflation",
     xlab="Unemployment (percent)",ylab="Inflation (percent)",las=1
     )

This looks fine. The x and y-axis labels are visible.

Next, we show the labels on two lines (note that \n is the new-line character).

plot(weo_usa$lur,weo_usa$pcpi_pch,main="US: Unemployment and inflation",
     xlab="Unemployment \n(percent)",ylab="Inflation \n(percent)",las=1
     )

As you can see the y-axis label is only partly visible. To fix that, we change the margins. Margins are set through a vector. The order is bottom, left, top, right. The defaults is c(5.1, 4.1, 4.1, 2.1). These numbers may look a bit strange, but it is the number of lines plus a little bit extra.

Let’s set the left margin to 5.1. We first store the old margins in a variable old_par, then change the margins, and at the end change it back to the old margins,

old_par=par()$mar
old_par
[1] 5.1 4.1 4.1 2.1
par(mar=c(5.1,5.1,4.1,2.1))
par(mar=old_par)

Let’s now apply this to the chart:

old_par<-par()$mar
par(mar=c(5.1,5.1,4.1,2.1))

plot(weo_usa$lur,weo_usa$pcpi_pch,main="US: Unemployment and inflation",
     xlab="Unemployment \n(percent)",ylab="Inflation \n(percent)",las=1
     )

par(mar=old_par)

Adjusting Outer Margins for Combined Charts

oma is used when you want to add titles or overall annotations outside the individual plots.

# Setting up outer margins for combined charts
par(oma=c(3, 3, 3, 3))  # Adds space around the entire set of plots

Let’s combine several plots into one figure.

Generate Sample Data

We will generate some sample data for a variety of charts.

set.seed(42)
x <- rnorm(100)
y <- rnorm(100)
groups <- gl(2, 50, labels = c("Group 1", "Group 2"))

Combining Charts

Now, let’s create a 2x2 combined chart layout, adjusting both mar and oma.

# Set up a 2x2 chart layout with custom inner and outer margins
par(mfrow=c(2,2))

# Top-left chart
plot(x, y, main="Scatter Plot",las=1)

# Top-right chart
boxplot(x, y, names=c("x", "y"), main="Boxplot",las=1)

# Bottom-left chart
hist(x, main="Histogram of x",las=1)

# Bottom-right chart
barplot(table(groups), main="Barplot of Groups",las=1)

# Adding a common title with the outer margin space
mtext("Combined Charts", outer=TRUE, cex=1.5, line=1)

In this example, mfrow sets the layout–two rows by two columns.

There is one problem. The overall title (which we set with mmtext) is not visible. That is because the outer margins are 0 by default. Let’s change the top margin We also change the margins of the individual plots, to have less room between the plots:

# Set up a 2x2 chart layout with custom inner and outer margins
par(mfrow=c(2,2))
par(mar=c(4, 2, 2, 2))
par(oma=c(2, 2, 3, 2))

# Top-left chart
plot(x, y, main="Scatter Plot",las=1)

# Top-right chart
boxplot(x, y, names=c("x", "y"), main="Boxplot",las=1)

# Bottom-left chart
hist(x, main="Histogram of x",las=1)

# Bottom-right chart
barplot(table(groups), main="Barplot of Groups",las=1)

# Adding a common title with the outer margin space
mtext("Combined Charts", outer=TRUE, cex=1.5, line=1)

Graphical Parameters

There are many graphical parameters you can set with par(). Some of the most commonly used include:

  • cex: Character expansion for text sizing.
  • col: Default plotting color.
  • pch: Plotting character (symbol) for points.
  • lty: Line type.
  • lwd: Line width.

Here’s an example of changing the point character and color:

# Save the original pch and col settings
original_pch <- par("pch")
original_col <- par("col")

# Set plot symbol to solid circle and color to blue
par(pch=19, col="blue")

# Create a scatter plot
plot(1:10, 1:10, main="Customized Plot Symbols and Colors", xlab="X-axis", ylab="Y-axis", las=1)

# Reset to original pch and col settings
par(pch = original_pch)
par(col = original_col)

Fonts and Text

Fonts and text can be adjusted using parameters like cex, font, and family.

Adjusting Text Size

The cex parameter controls text size:

# Save the original cex settings
original_cex <- par("cex")

# Set text size to 150% of default
par(cex=1.5)

# Create a plot
plot(1:10, 1:10, main="Plot with Adjusted Text Size", xlab="X-axis", ylab="Y-axis", las=1)

# Reset to original cex settings
par(cex = original_cex)

Changing Fonts

You can change the font family using the family parameter. This needs to be a font that’s installed on your system.

# Save the original family settings
original_family <- par("family")

# Change font family
par(family="Lucida Handwriting")

# Create a plot
plot(1:10, 1:10, main="Plot with Custom Font", xlab="X-axis", ylab="Y-axis")

# Reset to original family settings
par(family = original_family)

Advanced Layouts

For more complex layouts than what mfrow can handle, you might use the layout() function in combination with par(). This allows for non-uniform plot sizes.

Example: Advanced Layout with layout()

# Save the original par settings
original_layout <- par("oma")

# Define the layout matrix: two rows, first row with one plot (full width), second row with two plots (half width each)
layout(matrix(c(1, 2, 3, 3), nrow=2, byrow=TRUE))

# Adjust outer margins
par(oma=c(2, 2, 2, 2))

# Create the plots
plot(1:10, main="Plot 1 (Half Width)")
plot(1:10, main="Plot 2 (Half Width)")
plot(1:10, main="Plot 3 (Full Width)")

# Reset to original oma settings
par(oma = original_layout)

Combining par() with Other High-Level Plotting Functions

par() works in conjunction with high-level plotting functions like plot(), hist(), and boxplot(). The parameters set by par() will apply to these plots.

Conclusion

The par() function is your go-to tool for controlling the look and feel of plots in R. With careful adjustment of its parameters, you can produce professional-quality graphics tailored to your specific needs.