ramesesjd
ramesesjd

Reputation: 303

adding errorbars to individual points in faceted plots

I'm trying to make a faceted plot from a dataframe showing how one variable changes as a function of other variable. Each variable has an error associated with it. Here's a subset of the data I have; an ID column, the variables (SiO2 to FeO) and the errors associated with the variables (*_2stdev):

df<-structure(list(ID = structure(c(3L, 4L, 6L, 1L, 2L, 10L), .Label = c("P466-an1", "P466-an2", "P468-an1", "P468-an2", "P469-an1", "P470-an1", "P471-an1", "P472-an1", "P473-an1", "P474-an1", "P475-an1", "P475-an2", "P476-an1", "P476-an2", "P477-an1", "P478-an1", "P479-an1", "P480-an1"), class = "factor"), 
           SiO2 = c(54.5147, 56.2223, 52.8499, 52.0293, 53.4221, 52.9802), 
           TiO2 = c(0.5928, 0.5792, 0.5771, 1.1373, 1.0962, 1.1535), 
           Al2O3 = c(17.5404, 18.1921, 19.4737, 15.7752, 16.455, 16.4117), 
           FeO = c(6.2115, 5.8676, 5.4874, 4.5952, 4.4242, 4.109), 
           SiO2_2stdev = c(1.5232, 2.3578, 0.6374, 1.3331, 0.6535, 0.6977), 
           TiO2_2stdev = c(0.0638, 0.0637, 0.0357, 0.1024, 0.0422, 0.0282), 
           Al2O3_2stdev = c(0.4519, 0.4572, 0.2044, 0.6378, 0.6546, 0.0624), 
           FeO_2stdev = c(0.426, 0.3973, 0.1145, 0.1992, 0.1106, 0.0427)), 
          .Names = c("ID", "SiO2", "TiO2", "Al2O3", "FeO", "SiO2_2stdev", "TiO2_2stdev", "Al2O3_2stdev", "FeO_2stdev"), 
          row.names = c(NA, 6L), class = "data.frame")

Using the following code:

library(reshape2)
library(ggplot2)

m.df<-melt(df, id=c('ID','FeO'))

p<-ggplot(subset(m.df, variable %in% c('SiO2','TiO2','Al2O3')),aes(x=value, y=FeO))+
   geom_point()+
   facet_wrap(~ variable, ncol=1, scales="free_x")+
   theme_bw()

p

I get this plot:

plot with no errorbars

I would like to add the errorbars (vertical and horizontal) to this, but I don't know how to do this on a faceted plot.

Using geom_errorbar and geom_errorbarh, I've been able to plot these for individual plots from the unmelted dataframe. I suppose I could make all the plots with a loop, but I don't know how to add the errorbars with this method. Further, I'd like to see all the plots at once.

Thanks for reading this and any help is greatly appreciated! -R

edit As per aosmith's comment, I've added FeO_2stdev to the ID variables in melt. I'm now able to produce a plot with the correc vertical errorbars. So now I have trouble understanding how I can get geom_errorbarh to plot the correct errorbars on for each plot.

Below is the updated code I'm using, with the resulting plot.

library(reshape2)
library(ggplot2)

m.df<-melt(df, id=c('ID','FeO', 'FeO_2stdev'))
m.df$y.min<-m.df$FeO-m.df$FeO_2stdev
m.df$y.max<-m.df$FeO+m.df$FeO_2stdev

p<-ggplot(subset(m.df, variable %in% c('SiO2','TiO2','Al2O3')), aes(x=value, y=FeO))+
   geom_point()+
   facet_wrap(~ variable, ncol=1, scales="free_x")+
   theme_bw()+
   geom_errorbar(aes(ymin=y.min, ymax=y.max))

p

plot with vertical errorbars

Upvotes: 0

Views: 132

Answers (1)

aosmith
aosmith

Reputation: 36114

Having a dataset with one column of values and one column of 2 standard deviations will help with the horizontal error bars. This is essentially a data manipulation problem. There are many ways to achieve such a thing. I'm using tidyr with dplyr.

For example, if you start with m.df immediately after melting, you could

  1. Make a new variable to represent whether the row represents 2 standard deviations or the value using separate and then mutate with if_else.
  2. spread the dataset back into a wide format, with one column for the values and one for the 2 standard deviations. You could also use dcast from reshape2 if you are already familiar with it.

library(dplyr) library(tidyr)

m.df %>%
    separate(variable, c("variable", "metric")) %>%
    mutate(metric = if_else(is.na(metric), "value", metric)) %>%
    spread(metric, value)

         ID    FeO FeO_2stdev variable 2stdev   value
1  P466-an1 4.5952     0.1992    Al2O3 0.6378 15.7752
2  P466-an1 4.5952     0.1992     SiO2 1.3331 52.0293
3  P466-an1 4.5952     0.1992     TiO2 0.1024  1.1373
4  P466-an2 4.4242     0.1106    Al2O3 0.6546 16.4550
5  P466-an2 4.4242     0.1106     SiO2 0.6535 53.4221
...

Here's the whole process using gather from tidyr instead of melt for the same results:

df2 = df %>%
    gather(key, value, -ID, -contains("FeO")) %>%
    separate(key, c("variable", "metric")) %>%
    mutate(metric = if_else(is.na(metric), "value", metric)) %>%
    spread(metric, value)

Now the horizontal error bars can be added to your plot using value and 2stdev. Note that the column name 2stdev isn't syntactically correct so I use backticks around the variable name.

ggplot(df2, aes(x=value, y=FeO))+
    geom_point()+
    facet_wrap(~ variable, ncol=1, scales="free_x")+
    theme_bw() +
    geom_errorbar(aes(ymin = FeO - FeO_2stdev, ymax = FeO + FeO_2stdev)) +
    geom_errorbarh(aes(xmin = value - `2stdev`, xmax = value + `2stdev`))

enter image description here

Upvotes: 1

Related Questions