2

I need to create a unique box plot. I want it to represent the geometric mean instead of the median, and the top and bottom of the box to be the 90th and 10th percentiles. I have found information on how to add means and sd and how to extend wiskers on plots but not how to change the basic statistics. I would like to use ggplot2 because I'm familiar with it but I'm open to anything.

I'm plotting fecal coliform data by year with the following code:

library(psych)
library(dplyr)
library(zoo)
library(caTools)
library(ggplot2)
library(stats)

setwd("H:/MWQSampleData/GrowingAreaRawData")

setAs("character", "myDate", function(from) as.Date(from, format = "%m/%d/%Y"))

RawData <- read.csv("VaughnBay1989.csv", header = TRUE, colClasses = 
            c("factor", "factor", "myDate", "numeric", "factor", "numeric", "numeric","numeric"))

GrowingAreaYrSummary <- RawData %>%
  select(Year, FecalColiform) %>%
  group_by(Year)



Graph <- ggplot(GrowingAreaYrSummary, aes(x=Year, y=FecalColiform))
  geom_boxplot(outlier.shape = NA) +
  theme(axis.text.y = element_text(face = "bold", angle = 45, size = 14), 
        axis.text.x = element_text(face = "bold", angle = 45, size = 14, vjust = -0.005),
        panel.background = element_rect(fill = "ivory2"), 
        panel.grid.major = element_line(colour = "gray88"),
        plot.title = element_text(size = 18, face = "bold", vjust = -4),
        axis.title.y = element_text(size = 16, face = "bold"),
        axis.title.x = element_text(size = 16, face = "bold", vjust = -0.5),
        axis.ticks.x = element_line(size = 1.5, colour = "black"),
        panel.border = element_rect(colour = "black", fill = NA, size = 1)) +
  scale_y_continuous(breaks=seq(0,50,5), limits=c(0,50)) +
  geom_smooth(method="loess", se="TRUE", aes(group=1)) +
  ggtitle("Vaughn Bay Growing Area \n Fecal Coliform 1989 - 2015") +
  ylab("Fecal Coliform (fc/100 ml)") +
  xlab("Year") +
  annotate("text", x=10, y=43, label="Outliers Excluded \n from Graph")

Graph

I would like to make the same graph but with the new components. Any insight is appreciated. Thank you!

  • 2
    scroll down to the bottom of this page (http://docs.ggplot2.org/dev/geom_boxplot.html) it explains how to do it – MLavoie Jan 30 '16 at 00:07
  • If you want more help than MLavoie's link, then you should create a **minimal, reproducible example** ([see tips here](http://stackoverflow.com/q/5963269/903061)). We don't have your CSV (nor should we need it), it would be much better to use a little built in data or simulate a small data set to illustrate the problem. We also probably don't need 5 packages and 10 theme customizations to get the main idea across. – Gregor Thomas Jan 30 '16 at 00:10

1 Answers1

5

You can write a special-purpose function to pass to stat_summary:

# Return the desired percentiles plus the geometric mean
bp.vals <- function(x, probs=c(0.1, 0.25, 0.75, .9)) {
  r <- quantile(x, probs=probs , na.rm=TRUE)
  r = c(r[1:2], exp(mean(log(x))), r[3:4])
  names(r) <- c("ymin", "lower", "middle", "upper", "ymax")
  r
}

# Sample usage of the function with the built-in mtcars data frame
ggplot(mtcars, aes(x=factor(cyl), y=mpg)) +
  stat_summary(fun.data=bp.vals, geom="boxplot")

I have a function like this that I use for custom percentiles in boxplots and I originally adapted it from this SO answer.

Community
  • 1
  • 1
eipi10
  • 91,525
  • 24
  • 209
  • 285