Beasterfield
Beasterfield

Reputation: 7113

Making a ternary plot

I want to plot the projection of 3-dimensional data on their simplex using ggplot2. I thought I could manage the transformation on cartesian coordinates using coord_trans(), but do not know how to do it exactly.

This is what I tried:

simplex.y  <- function( x1, x2, x3 ) {
  return( sqrt(0.75) *  x3 / (x1+x2+x3) )
} 
simplex.x  <- function( x1, x2, x3 ) {
  return( (x2 + 0.5 * x3) / (x1+x2+x3) )
}

x  <- data.frame(
  x1 = c( 0, 0, 1, 0.1, 0.6, 0.2 ),
  x2 = c( 0, 1, 0, 0.3, 0.2, 0.8 ),
  x3 = c( 1, 0, 0, 0.6, 0.2, 0.0 )
)

require(ggplot2)
ggplot( data = x, aes( x = c(x1, x2, x3), y = c(x1, x2, x3)) ) +
  geom_point() +
  coord_trans( x="simplex.x", y="simplex.y" )

Any suggestions are appreciated. Many thanks!

Upvotes: 13

Views: 16287

Answers (7)

V&#237;ctor
V&#237;ctor

Reputation: 21

The function triax.plot(), from the plotrix package also draws ternary plots:

require(plotrix)

x  <- data.frame(
  x1 = c( 0, 0, 1, 0.1, 0.6, 0.2 ),
  x2 = c( 0, 1, 0, 0.3, 0.2, 0.8 ),
  x3 = c( 1, 0, 0, 0.6, 0.2, 0.0 )
)

triax.plot(x, pch=16,col.symbols="red")

Upvotes: 1

Nicholas Hamilton
Nicholas Hamilton

Reputation: 10526

As mmann1123 highlighted, using ggtern, the following can be achieved:

Output

With the following simple codeblock:

x  <- data.frame(
  x1 = c( 0, 0, 1, 0.1, 0.6, 0.2 ),
  x2 = c( 0, 1, 0, 0.3, 0.2, 0.8 ),
  x3 = c( 1, 0, 0, 0.6, 0.2, 0.0 )
)

ggtern(data=x,aes(x2,x1,x3)) + 
   geom_mask() +
   geom_point(fill="red",shape=21,size=4) + 
   theme_bw() +
   theme_showarrows() +
   theme_clockwise()

Upvotes: 19

Jo&#227;o
Jo&#227;o

Reputation: 771

For completeness, you can try the good old ade4 package:

x  <- data.frame(
  x1 = c( 0, 0, 1, 0.1, 0.6, 0.2 ),
  x2 = c( 0, 1, 0, 0.3, 0.2, 0.8 ),
  x3 = c( 1, 0, 0, 0.6, 0.2, 0.0 )
)

require(ade4)
triangle.plot(x)

Upvotes: 1

Martin Smith
Martin Smith

Reputation: 4077

The R package Ternary produces ternary plots from matrices and data.frames using the standard graphics functions.

Ternary plot created with R package Ternary

The above plot is created with:

x  <- data.frame(
  x1 = c( 0, 0, 1, 0.1, 0.6, 0.2 ),
  x2 = c( 0, 1, 0, 0.3, 0.2, 0.8 ),
  x3 = c( 1, 0, 0, 0.6, 0.2, 0.0 )
)
TernaryPlot()
TernaryPoints(x, col='red')

Upvotes: 2

mmann1123
mmann1123

Reputation: 5295

Use the ggtern library you can read about it here. http://ggtern.com/

Upvotes: 1

Drew Steen
Drew Steen

Reputation: 16617

The ternaryplot function in the vcd package does a nice job of making classical ternary plots from non-normalized data:

require(vcd)
#ternaryplot takes matrices but not data frames
xM <- as.matrix(x)
ternaryplot(xM)

enter image description here

Upvotes: 7

joran
joran

Reputation: 173667

coord_trans doesn't do what you seem to think it does. It will transform the x and y coordinates of a plot that's already 2D, but you have 3D data.

Just transform the data yourself and then plot it:

simplex.y  <- function(x) {
  return( sqrt(0.75) *  x[3] / sum(x) )
} 
simplex.x  <- function(x) {
  return( (x[2] + 0.5 * x[3]) / sum(x) )
}

x  <- data.frame(
  x1 = c( 0, 0, 1, 0.1, 0.6, 0.2 ),
  x2 = c( 0, 1, 0, 0.3, 0.2, 0.8 ),
  x3 = c( 1, 0, 0, 0.6, 0.2, 0.0 )
)

newDat <- data.frame(x = apply(x,1,simplex.x),
                y = apply(x,1,simplex.y))

ggplot(newDat,aes(x = x,y = y)) + 
    geom_point()

Note that I rewrote your transformation functions to be more R-like. Also, you shouldn't be passing expressions like x = c(x1,x2,x3) inside of aes(). You map a single variable in your data frame to a single aesthetic.

Upvotes: 1

Related Questions