Search code examples
rggplot2faceterrorbar

Sorting errorbars with a faceted grid?


I have been struggling for a few days with this one- and cant find a slice of code to help. I have a multiple variable barplot that is faceted in ggplot2, and I finally worked it out so it looks great and conveys the data I want to show. Unfortunately, when I add the error bars to the graphic, they are all out of order and floating across the whole barplot. (barplot example of the bane of my existence)

The Data: (thanks, I forgot about dput)

 > dput(plant_ag)

    structure(list(worms = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 
     2L, 1L, 2L, 1L, 2L), .Label = c("No", "Yes"), class = "factor"), 
    poll_level = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 1L, 1L, 
    2L, 2L, 3L, 3L), .Label = c("Low", "Medium", "Very"), class = "factor"), 
    variable = structure(c(7L, 7L, 7L, 7L, 7L, 7L, 10L, 10L, 
    10L, 10L, 10L, 10L), .Label = c("biomass", "cu_seed", "pb_seed", 
    "zn_seed", "cu_buck", "pb_buck", "zn_buck", "cu_rye", "pb_rye", 
    "zn_rye"), class = "factor"), x.mean = c(0.9945992584, 4.645085363, 
    198.390869802, 58.43054462, 3795.1789451, 2883.8860731, 942.59827934, 
    1313.1415081, 707.165653286, 1529.33515045, 3811.442312, 
    6149.4490085), x.sd = c(3.14519901565836, 14.68904967299, 
    176.524518210961, 61.362498383762, 554.023490328341, 541.012498962109, 
    224.078432824798, 221.039876468939, 468.567696912978, 1021.25312103485, 
    2431.58456925777, 3004.85636935088), x.n = c(10, 10, 10, 
    10, 10, 10, 10, 10, 10, 10, 10, 10), se = c(0.9945992584, 
    4.645085363, 55.8219540410509, 19.4045257811089, 175.197610667382, 
    171.083173933975, 70.8598222247401, 69.8989463364104, 148.174116022446, 
    322.948593002573, 768.934556217399, 950.219016881294), 
    names = c("No EW/ Low Soil", 
    "Yes EW/ Low Soil", "No EW/ Medium Soil", "Yes EW/ Medium Soil", 
    "No EW/ Very Soil", "Yes EW/ Very Soil", "No EW/ Low Soil", 
    "Yes EW/ Low Soil", "No EW/ Medium Soil", "Yes EW/ Medium Soil", 
    "No EW/ Very Soil", "Yes EW/ Very Soil"), 
     ymin = c(0, 8.88178419700125e16, 
    142.568915760949, 39.0260188388911, 3619.98133443262, 2712.80289916603, 
    871.73845711526, 1243.24256176359, 558.991537263554, 1206.38655744743, 
    3042.5077557826, 5199.22999161871), ymax = c(1.9891985168, 
    9.290170726, 254.212823843051, 77.8350704011089, 3970.37655576738, 
    3054.96924703397, 1013.45810156474, 1383.04045443641, 855.339769308446, 
    1852.28374345257, 4580.3768682174, 7099.66802538129)), 
 .Names =   c("worms", 
"poll_level", "variable", "x.mean", "x.sd", "x.n", "se", "names", 
"ymin", "ymax"), row.names = c(NA, -12L), class = "data.frame")
> 

The code:

########### THE GRAPH STARTS HERE
library(ggplot2)

p <- ggplot(data = plant_ag, aes(x = factor(worms), fill = factor(variable), y = x.mean,
                                 group=variable))
p <- p + geom_bar(colour="black",stat = "identity",position = position_dodge(.95))
p <- p + facet_grid(. ~ poll_level)
p <- p + geom_errorbar(aes(ymin=plant_ag$ymin, ymax=plant_ag$ymax), width=0.2,  stat="identity", 
                       position = position_dodge(1))
          +  facet_wrap(worms ~poll_level, ncol=4) 
p <- p + theme_bw () + theme(legend.position = c(0.15, 0.8)) + 
  ggtitle("Zinc in Plants by Soil Pollution Level") +ylab("Zn concentration in plants, ppm") + 
  xlab("Earthworm Community Present")
p <- p + scale_fill_manual(values=c('darkgray','lightblue'), 
                           name="Experimental\nPlant",
                           labels=c("Buckwheat", "Rye")) 
p
######### END OF COMMAND

Any help (or commiseration) is very, very welcome! Thanks for all you folks do, it is an unbelievable help to all of us N00B's.


Solution

  • Changing to aes(ymin=ymin, ymax=ymax) in geom_errorbar solves the ordering problem for the errorbars. You've passed the data frame to ggplot in your initial call to the ggplot function and don't need to refer to it again. Using the data frame name inside aes in geom_errorbar overrides the ordering along the x-axis set by ggplot, so that the error bars are plotted based on their order in the data frame, rather than the category ordering in the plot.

    Also, your code has both facet_wrap and facet_grid, but you can only use one or the other. Below is the updated plot code, with facet_wrap commented out. I also set the y scale, because your data has a huge value for one of the errorbars that messes up the plot.

    The code below also shows how to use + to chain plot components together.

    p <- ggplot(data = plant_ag, aes(x = factor(worms), fill = factor(variable), 
                                     y = x.mean, group=variable)) + 
      geom_bar(colour="black", stat="identity", position=position_dodge(.95)) + 
      facet_grid(. ~ poll_level) + 
      geom_errorbar(aes(ymin=ymin, ymax=ymax), width=0.2, stat="identity",
                    position = position_dodge(1)) +  
      scale_y_continuous(limits=c(0,8000)) +
    #  facet_wrap(worms ~ poll_level, ncol=4) + 
      theme_bw() + theme(legend.position = c(0.15, 0.8)) + 
      ggtitle("Zinc in Plants by Soil Pollution Level") +
      labs(y="Zn concentration in plants, ppm",
           x="Earthworm Community Present") + 
      scale_fill_manual(values=c('darkgray','lightblue'), 
                        name="Experimental\nPlant",
                        labels=c("Buckwheat", "Rye")) 
    

    enter image description here