Ternary Plots in GGPLOT/R


Ternary Plot using ggplot2

>DOWNLOAD THE TEMPLATE<

Ternary plots are great for displaying trivariate data (or more), and are used a lot in geochemistry. R is a great tool for plotting data and has built-in capabilities for dealing with trivariate data:

Many people, however, use the ggplot2 package for R which sadly has no native ternary plotting capability. A hack is provided by Sean Mulcahy, but the code here deals with an alternative, somewhat adapted way of achieving similar results.

How does it work? Basically the code takes 3 variables (A, B, C) and converts it into XY data. The ternary plot is actually plotted on a [hidden] X-Y plot, where the X values are corrected for Y thus allowing ternary data to be plotted onto the XY plot area.

Features of the template

  • Lists of common customisation parameters (colour, size etc) built into the preamble to make visual changes quick and correct
  • Automatic correction of ABC data into ternary plotting coordinates
  • Systematically commented allowing you to understand what’s doing what.

What next? I’m working on a set of templates for common geochemical discrimination diagrams which will allow you to simply import and display your data and discriminate between your samples.

# Load Packages
	
	library (cwhmisc)
	library (ggplot2)
	library (grid)
	library (scales)

# Select Data Source 
	
	# Select csv file
	data = mtcars	
	
	# Define apices
	#t = top, l = left, r = right
	data$l = data$mpg		# e.g. data$t = data$a*100
	data$t = data$wt*10
	data$r = data$hp/5


# Plot customisation
	
	# Customise: Colours
	colour.1 = "white"		# Panel background colour
	colour.2 = "white"		# Plot area background colour
	colour.3 = "black"		# Outer text colour
	colour.4 = "black"		# Plot outline colour
	colour.5 = "lightgrey"		# Gridline colour
	colour.6 = "white"		# Legend box outline colour
	
	# Customise: Font sizes
	fs.r = 1.168
	fs.1 = 6
	fs.2 = (fs.1*2) * (fs.r^4)
	fs.3 = fs.1 * (fs.r^5)
	
	# Labels & Title
	title = "Ternary Template v.09.13"
	apices = c("MPG", "Horse Power", "Weight (x10)") 	# Left, Right, Top

	# Other
	gridlines = F		# Turn gridlines on/off with T/F






##################################################################################

# Convert data to %
	data$total = data$l+data$r+data$t
	data$t = (data$t/data$total)*100
	data$l = (data$l/data$total)*100
	data$r = (data$r/data$total)*100

# Convert abc into xy
	data$x = (100-((data$t/2)+((100-data$t)*(data$l/(data$l+data$r)))))
	data$y = data$t

	#if t = 100 then x should be 50 
	n = nrow (data)
	for (i in 1:n) {
		temp = data[i,]
		if (temp$y == 100) {temp$x = 50}
		data[i,] = temp	
	}

# Coordinates for triangle
	tri = data.frame (c(0, 100, 50, 0), c(0, 0, 100, 0))
	colnames(tri) = c("x", "y")

# Coordinates for grid
	x1 = seq (10, 90, 10)
	x2 = seq (5, 45, 5)
	x3 = seq (55, 95, 5)
	x4 = seq (45, 5, -5)
	y1 = 0
	y2 = seq (10, 90, 10)
	y3 = seq (90, 10, -10)
	grid = data.frame (x1, x2, x3, x4, y1, y2, y3)


# Open new quartz window
	dev.new (height = 10*0.866025, width = 10)
	if (gridlines == T) {gridalpha = 1} else {gridalpha = 0}


	
	
ggplot (data = data, aes (x = x, y = y)) +
	
	# Shapes, lines, text
	geom_polygon (data = tri, fill = colour.2) +
	
	geom_segment (data = grid, 
		aes (x = x1, y = y1, xend = x2, yend = y2), 
		linetype = "dashed", size = 0.5, colour = colour.5, alpha = gridalpha) +
	geom_segment (data = grid, 
		aes (x = x1, y = y1, xend = x3, yend = y3), 
		linetype = "dashed", size = 0.5, colour = colour.5, alpha = gridalpha) +
	geom_segment (data = grid, 
		aes (x = x4, y = y3, xend = x3, yend = y3), 
		linetype = "dashed", size = 0.5, colour = colour.5, alpha = gridalpha) +
	annotate ("text", label = apices, x = c(-5, 105, 50), y = c(-5, -5, 105), size = fs.1, colour = colour.3) +
	labs (title  = title, colour = "No Cylinders") +
	geom_path (data = tri, size = 0.5, colour = colour.4) +
	
	# Appearance controls
	coord_fixed (ratio = 0.866025) +
	scale_x_continuous (limits = c(-20, 120), expand = c(0,0)) +
	scale_y_continuous (limits = c(-20, 120), expand = c(0,0)) +
	theme (
		
		# Panel and plot attributes
		plot.title = element_text (size = fs.2, colour = colour.3), 	# Plot title
		plot.margin = unit (c(3, 4, 3, 3), "lines"), 					# Plot margins
		plot.background = element_rect (colour = F, fill = colour.1),
		panel.border = element_rect (colour = F, fill = F, size = 1), 	# Axis colours
		panel.grid.major = element_blank (), 							# Remove major grid
		panel.grid.minor = element_blank (), 							# Remove minor grid
		panel.background = element_rect (fill = colour.1), 				
		
		# Legend attributes
		legend.background = element_rect (colour = colour.6, size = 0.3, fill = "white"),
		legend.justification = c(1, 1),
		legend.position = c(0.9, 0.9), 				# Put the legend INSIDE the plot area
		legend.key = element_blank (), # switch off the rectangle around symbols in the legend
		legend.box.just = "bottom",
		legend.box = "horizontal",
		legend.title = element_text (size = fs.3, colour = colour.3), # switch off the legend title
		legend.text = element_text (size = fs.3, colour = colour.3), #sets the attributes of the legend text
		
		# Axis attributes
		axis.title.x = element_blank (),
		axis.title.y = element_blank (),
		axis.text.x = element_blank (),
		axis.text.y = element_blank (),
		axis.ticks = element_blank ()
		) +
	
	# Data layer
	geom_point (aes(colour = factor(cyl)),size = 6)

	
ggsave ("/Users/s0679701/Desktop/ternary.png", dpi = 100)
	

Advertisements

One thought on “Ternary Plots in GGPLOT/R

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s