4

I am still new to R. I agreed to help a friend replot his graphs however one of his plot designs is proving quite hard to reproduce. This is because he inserted a Y-axis break followed by a scale alteration on a barplot. This is illustrated by the example picture below. Example image of plot

Unexpectedly this is proving hard to implement. I have attempted using:

barplot() #very hard to implement with all elements, couldn't make it

gap.barplot() #does not allow for grouped barplots

ggplot() #after considerable time learning the basics found it will not allow breaking the axis

Please would anyone have an intuitive way of plotting this on R? NOTE: I know likely the best way to show this information is by log-transforming the data to make it fit the scale but I'd like to propose that with the two plot options in hands.

Some summarized data is given below if anyone would like to test with:

  AAP    Sex    min     max       mean          sd          
1  12d Female 100.97  702.36  444.07389  197.970342  
2  12d   Male  24.69 1090.15  469.48200  262.893780  
3  18d Female 195.01 4204.68 1273.72000 1105.568111 
4  18d   Male 487.75 4941.30 1452.37937 1232.659688 
5  24d Female 248.58 3556.11 1583.09958  925.263382 
6  24d   Male 556.60 4463.22 1589.50318  973.225661 
7   3d Female   4.87   16.93   12.86571    4.197987   
8   3d   Male   3.23   16.35    8.13000    5.364383   
9   6d Female   3.20   37.63   15.07500   11.502331   
10  6d   Male   4.64   94.93   28.39300   30.671206   
Scientist
  • 1,061
  • 2
  • 13
  • 30
  • 1
    [This](https://stackoverflow.com/questions/19612348/break-x-axis-in-r) might help you a bit. – Anders Ellern Bilgrau Jun 22 '17 at 08:50
  • 3
    This is a really bad plot. As you pointed out already, go with a log transformation or, as recommended in the link by @AEBilgrau, use `facet_wrap` to split the plot into two plots with `scales = 'free'`. – LAP Jun 22 '17 at 08:51
  • Thanks @AEBilgrau for the link, yes I had read that thread before and wondered whether there was a simpler solution. What I am doing is first building my suggestion log-transformed and using yours and others' comments to convince my friend that this kind of plot is a bit of a joke. I am afraid too many scientists follow low stats standards... – Scientist Jun 22 '17 at 11:30

2 Answers2

10

The basic steps involved are the same whichever graphics package you use:

  • Transform the data into the Y scale that you want
  • Provide some indication of the break in scale
  • Update the y-axis to show the new scale

So an example in ggplot might look like

library(ggplot2)
dput (dat)
#structure(list(AAP = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 
#4L, 5L, 5L), .Label = c("12d", "18d", "24d", "3d", "6d"), class = "factor"), 
#Sex = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), .Label = c("Female", 
#"Male"), class = "factor"), min = c(100.97, 24.69, 195.01, 
#487.75, 248.58, 556.6, 4.87, 3.23, 3.2, 4.64), max = c(702.36, 
#1090.15, 4204.68, 4941.3, 3556.11, 4463.22, 16.93, 16.35, 
#37.63, 94.93), mean = c(444.07389, 469.482, 1273.72, 1452.37937, 
#1583.09958, 1589.50318, 12.86571, 8.13, 15.075, 28.393), 
#sd = c(197.970342, 262.89378, 1105.568111, 1232.659688, 925.263382, 
#973.225661, 4.197987, 5.364383, 11.502331, 30.671206)), .Names = c("AAP", 
#"Sex", "min", "max", "mean", "sd"), class = "data.frame", row.names = c(NA, 
#-10L))

#Function to transform data to y positions
trans <- function(x){pmin(x,40) + 0.05*pmax(x-40,0)}

yticks <- c(0, 20, 40, 500, 1000, 1500, 2000)

#Transform the data onto the display scale
dat$mean_t <- trans(dat$mean)
dat$sd_up_t <- trans(dat$mean + dat$sd)
dat$sd_low_t <- pmax(trans(dat$mean - dat$sd),1) #

ggplot(data=dat, aes(x=AAP, y=mean_t, group=Sex,fill=Sex)) +
  geom_errorbar(aes(ymin=sd_low_t, ymax=sd_up_t),position="dodge") + 
  geom_col(position="dodge") +
  geom_rect(aes(xmin=0, xmax=6, ymin=42, ymax=48), fill="white") +
  scale_y_continuous(limits=c(0,NA), breaks=trans(yticks), labels=yticks) +
  labs(y="Relative titer of CLas")

Output plot

Note that I haven't got exactly the same error bars as you're example, and the resulting output would probably not please Hadley Wickham, the author of ggplot2.

Miff
  • 7,486
  • 20
  • 20
  • This is just great, thanks for taking it so deeply! I am nonetheless first preparing a much neater log-transformed version of his data to dissuade him. On the error bars, yes I had already changed his data summary to SD, instead of his originally plotted SE and forgot to note here. – Scientist Jun 22 '17 at 11:34
2

@Miff I'd like to use your code above but I'm not doing something right:

trans <- function(x){pmin(x,15000) + 0.05*pmax(x-15000,0)}
yticks <- c(0, 5000, 10000, 15000, 30000, 40000)
p <- 
  labdata_N %>%
  ggplot(aes(x = reorder(type, measure), weight = measure, fill = type, alpha = Tobacco.Constituent)) +
  geom_bar(position = "dodge", width = 0.75) +
  scale_alpha_manual(values = c(0.4, 1)) +
  geom_rect(aes(xmin=0, xmax=12.5, ymin=15000, ymax=16000), fill="white") +
  scale_y_continuous(limits=c(0,NA), breaks=trans(yticks), labels=yticks) +
  labs(x = "SLT type", y = "Nitrosamine level") +
  scale_fill_manual(values=mycols,
                    labels=c(type)) +
  theme(legend.position = "bottom",
        legend.title = element_blank(),
        axis.text = element_text(size=12),
        axis.title = element_text(size=14), 
        plot.title = element_text(size=14),
        legend.text = element_text(size=9),
        panel.background = element_rect(fill =  "grey90"))
print(p)

I get something like this: enter image description here

SamV
  • 118
  • 1
  • 7
  • This is in between an answer and a comment to another answer. I think it can be borderline useful to someone else, but at same time perhaps it's better for discussion elsewhere?.. – Scientist Dec 03 '20 at 13:36