Day: March 3, 2014

Multiple plots

Posted on Updated on

Plotting multiple curves and datasets on the same graph

It is quite common that we want to display different curves on the same graph, and / or display different sets of data in order to investigate the parameter space being covered.

This is often done when looking at various galaxy cluster datasets and comparing, for instance, the scaling relations derived for each sample. Let's consider, as an example, 3 samples which I will call A, B and C. Let's assume further that the L-M scaling relation has been derived for each sample. The results for the normalisation Alm and slope blm are summarised in the table below.

Sample Alm blm
A 0.76\pm 0.08 1.34\pm 0.05
B 0.59\pm 0.11 1.64\pm 0.23
C 1.13\pm 0.35 2.42\pm 0.46

Data

First, let's generate three data sets…

dat1 <- data.frame(
     "M"=seq(13.5,14.6,0.1),
     "L"=rnorm(12,43*(seq(13.5,14.6,0.1)/14)**1.33,0.4)
)

dat2 <- data.frame(
     "M"=seq(14,15.5,length.out=25),
     "L"=rnorm(25,44.5*(seq(14,15.5,length.out=25)/14.75)**1.4,0.32)
)

dat3 <- data.frame(
     "M"=seq(14,15,length.out=8),
     "L"=rnorm(8,43*(seq(14,15,length.out=8)/14.5)**1.33,0.4)
)   

To display these three datasets easily with ggplot, we have to create a new data frame which holds all these data frames + an extra parameter (which I will call sample) which refers to the name of the data sample for each index value.

dat <- data.frame(
    "M"=c(dat1$M,dat2$M,dat3$M),
    "L"=c(dat1$L,dat2$L,dat3$L),
    "sample"=c(rep("dat1",length(dat1$M)),rep("dat2",length(dat2$M)),rep("dat3",length(dat3$M)))
)

N.B. There is a simpler way to merge different data frames using dplyr but let's leave this for the moment. I might update the post later and/or explain how to do this in another post.

Fitting parameters

In the same way that we created a combined data frames to hold the data values, we are going to create a combined data frame containing the slope and normalisation values for each of our samples.

##plot limits
mmin <- 13.5
mmax <- 15.5
lmin <- 43.5
lmax <- 45.5

##create a function to hold errors in log space
err <- function(x,logAe,Be) {
  ##form is y = B*logx + logA
  err <- sqrt( (Be*x)**2 + logAe**2 )
  return(err)
}

##these lines are created from real data so I correct here for 
##the pivot mass and luminosity
xlinem <- seq(mmin,mmax,0.1)
ylinem1 <- 44.76 + 1.34*(xlinem - 15)
ylinem2 <- 44.77 + 1.64*(xlinem - 15)
ylinem3 <- 44.75 + 2.42*(xlinem - 14.7)
em1 <- err(xlinem-15,0.08/0.76/log(10),0.05)
em2 <- err(xlinem-15,0.11/0.59/log(10),0.23)
em3 <- err(xlinem-14.7,0.35/1.13/log(10),0.46)

fitdat <- data.frame(
    "x"=rep(xlinem,3),
    "y"=c(ylinem1,ylinem2,ylinem3),
    "yup"=c(ylinem1+em1,ylinem2+em2,ylinem3+em3),
    "ylow"=c(ylinem1-em1,ylinem2-em2,ylinem3-em3),
    "fit"=c(rep(1,length(xlinem)),rep(2,length(xlinem)),rep(3,length(xlinem)))
)

Plot

Let's create the plot!!

library(ggplot2)

p1 <- ggplot(data=fitdat, aes(x=x, y=y,group=fit))+
    geom_line(data=fitdat, aes(linetype=factor(fit)))+
    geom_ribbon(data=fitdat, aes(ymin=ylow, ymax=yup,fill=factor(fit)),
    alpha=0.55)+
    geom_point(data=dat,aes(x=M,y=L,group=sample,colour=factor(sample),
    shape=factor(sample),size=factor(sample)))+
    xlab(expression(paste("log(",M,"/",h[70],M[sol],"])"))) +
    ylab(expression(paste("log(",L,"/",h[70]^2,"/[",erg,~s^{-1},"])")))

plot of chunk unnamed-chunk-1

Add a nice legend

##add nice colours
mycolours <- c("#aaaaf0","#f0aaf0","#f0f0aa","#aaf0aa")
mycolours2 <- c("#7f7fe8","#e87fe8","#e8e87f","#7fe87f")

p1+theme_bw(16) +
    theme(legend.justification=c(1,0), legend.position=c(1,0))+
    scale_colour_manual(name="Data",labels=c("Dat1","Dat2","Dat3"),
    values=c(mycolours2[1],mycolours2[2],mycolours2[4]))+
    scale_shape_manual(name="Data",labels=c("Dat1","Dat2","Dat3"),
    values=c(16,1,8))+
    scale_size_manual(name="Data",labels=c("Dat1","Dat2","Dat3"),
    values=c(2.8,2.8,2.8))+
    scale_linetype_manual(name="Fit",breaks=c(1,2,3),label=c("A","B","C"),
    values=c("dashed","twodash","solid"))+
    scale_fill_manual(name="Fit",breaks=c(1,2,3),label=c("A","B","C"),
    values=c(mycolours[1],mycolours[2],mycolours[4]))

plot of chunk data+combined+fit+plot+legend

<

p>Note that in creating these plots, I have assumed that the L-M relations were not derived from the 3 datasets… which seems obvious considering the poor agreement between the data and the fits!