4

I've spent quite a bit of time trying to develop a specific geom_bar plot with 2 y-axes (the dual-axes are a work requirement).

I've made the plots look acceptable, except there are some inaccuracies with the bar width and bar placement that I can't explain/fix.

The current plot looks like this: enter image description here

I realize it's hard to see, but some of the biggest issues are as follows:

(1) The bar widths vary. For example, in the N2T_1 facet, the green bars are different widths. I've tried setting width in geom_bar, which I found out was actually using a proportion of the space. I also tried adjusting the width in combination with position_dodge, which is my current code.

(2) The bars are not located exactly where they should be. In N2U_2, the tallest green bar occurs in 1999 according to the data, but when zoomed in on the ggplot, it shows up in 1998, while the 2000 value shows up in 1999.

(3) The shifted bars are not consistently shifted. In N2U_6,the tallest green bar should occur in 2008, but it is appearing in 2009 in the graph.

I'm not sure if I've made an error in my code, or if I'm missing something that should be in there. I'd appreciate any suggestions for how to fix these issues.

Current code:

# Left y-axis
p1 <- ggplot(data=DSCORE_CankDamage_N2, aes(x=Year, y=Dscore, group=Unique_ID_Tree))
p1 <- p1 + geom_rect(data=DSCORE_CankDamage_N2, aes(xmin=1965, xmax=1967, ymin=min(Dscore, na.rm=T), ymax=max(Dscore, na.rm=T)), alpha=0.1, fill="light goldenrod")
p1 <- p1 + geom_rect(data=DSCORE_CankDamage_N2, aes(xmin=1995, xmax=1997, ymin=min(Dscore, na.rm=T), ymax=max(Dscore, na.rm=T)), alpha=0.1, fill="light goldenrod")
p1 <- p1 + geom_rect(data=DSCORE_CankDamage_N2, aes(xmin=1999, xmax=2001, ymin=min(Dscore, na.rm=T), ymax=max(Dscore, na.rm=T)), alpha=0.1, fill="light goldenrod")
p1 <- p1 + geom_rect(data=DSCORE_CankDamage_N2, aes(xmin=2007, xmax=2009, ymin=min(Dscore, na.rm=T), ymax=max(Dscore, na.rm=T)), alpha=0.1, fill="light goldenrod")
p1 <- p1 + geom_hline(color="blue", linetype="dashed", aes(yintercept=0))
p1 <- p1 + geom_line(color="black")
p1 <- p1 + scale_x_continuous(limits=c(1945,2015), breaks=seq(1950,2010,10))
p1 <- p1 + ylab("Dscore")
p1 <- p1 + ggtitle("Annual Tree Decline (Dscore) and Total Canker Width (cm) per Year, Site N2")
p1 <- p1 + theme_bw() + theme(plot.margin=unit(c(1,1,1,1), "lines"),
plot.title=element_text(hjust=0.5, face="bold", family="Times New Roman", size=12, color="black"),
axis.title=element_text(size=12, family="Times New Roman", color="black"),
axis.text.y=element_text(size=10, family="Times New Roman", color="black"),
axis.text.x=element_text(size=10, family="Times New Roman", color="black", angle=90, vjust=0.5),
strip.text=element_text(size=9, family="Times New Roman"),
strip.background=element_rect(fill="azure2", colour="black",size=0.5),
strip.text.x=element_text(margin=margin(.1, 0, .1, 0, "cm")))
p1 <- p1 + facet_wrap(~Unique_ID_Tree, ncol=3, nrow=4)

# Right y-axis
p2 <- ggplot(data=DSCORE_CankDamage_N2, aes(x=Year, y=Cank_Width_cm))
p2 <- p2 + geom_bar(fill="darkgreen", alpha=0.6, width=0.6, position=position_dodge(width=0.9), stat="identity")
p2 <- p2 + facet_wrap(~Unique_ID_Tree, ncol=3, nrow=4)
p2 <- p2 + theme(plot.margin=unit(c(1,1,1,1), "lines"),
axis.title.y=element_text(size=12, color="black"),
axis.text=element_text(size=10, family="Times New Roman", color="black"),
panel.grid.minor = element_blank(),
panel.grid.major = element_blank(),
panel.background = element_rect(fill="transparent", colour = NA),
plot.background = element_rect(fill = "transparent", colour = NA))

# Combine left y-axis with right y-axis
p <- ggplot_dual_axis_facet(p1, p2)
grid.newpage()
png("DscoreWidthCankersClimate_N2.png", width=1000, height=600, units="px")
grid.draw(p)
grid.text("Width of Cankers (cm) per Year, per Tree", x=unit(0.95, "npc"), y=unit(0.5, "npc"), rot=90, gp=gpar(col="black", fontsize=12, fontfamily="Times New Roman"))
dev.off()

Dual-axis function developed by another user from an earlier question:

#Plotting 2 axes, writing a dual axis plot function WITH FACET_WRAP!:
ggplot_dual_axis_facet <- function(p1, p2) {
  #Extract gtable
  library(gtable) # loads the grid package
  g1 <- ggplot_gtable(ggplot_build(p1))
  g2 <- ggplot_gtable(ggplot_build(p2))
  #Overlap the panel of the 2nd plot on that of the 1st plot
  pp <- c(subset(g1$layout, grepl("panel",name), se = t:r))
  g <- gtable_add_grob(g1, g2$grobs[grep("panel",g2$layout$name)], 
                       pp$t, pp$l, pp$b, pp$l)
  #Tweak axis position and labels
  ia <- which(grepl("axis_l",g2$layout$name) | grepl("axis-l",g2$layout$name))
  ga <- g2$grobs[ia]

  axis_idx <- as.numeric(which(sapply(ga,function(x) !is.null(x$children$axis))))

  for(i in 1:length(axis_idx)){
    ax <- ga[[axis_idx[i]]]$children$axis
    ax$widths <- rev(ax$widths)
    ax$grobs <- rev(ax$grobs)
    ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
    g <- gtable_add_cols(g, g2$widths[g2$layout[ia[axis_idx[i]], ]$l], length(g$widths) - 1)
    g <- gtable_add_grob(g, ax, pp$t[axis_idx[i]], length(g$widths) - i, pp$b[axis_idx[i]])
  }
  # Display plot with arrangeGrob wrapper arrangeGrob(g)
  library(gridExtra)
  grid.newpage()
  return(arrangeGrob(g))
}

Reproducible sample (reduced to 1990-2012 and just 3 samples to save space):

    DSCORE_CankDamage_N2 <- structure(list(Year = c(1990, 1990, 1990, 1991, 1991, 1991, 1992, 
1992, 1992, 1993, 1993, 1993, 1994, 1994, 1994, 1995, 1995, 1995, 
1996, 1996, 1996, 1997, 1997, 1997, 1998, 1998, 1998, 1999, 1999, 
1999, 2000, 2000, 2000, 2001, 2001, 2001, 2002, 2002, 2002, 2003, 
2003, 2003, 2004, 2004, 2004, 2005, 2005, 2005, 2006, 2006, 2006, 
2007, 2007, 2007, 2008, 2008, 2008, 2009, 2009, 2009, 2010, 2010, 
2010, 2011, 2011, 2011, 2012, 2012, 2012), Unique_ID_Tree = c("N2T_1", 
"N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", 
"N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", 
"N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", 
"N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", 
"N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", 
"N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", 
"N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", 
"N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", 
"N2T_1", "N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6", "N2T_1", 
"N2U_2", "N2U_6", "N2T_1", "N2U_2", "N2U_6"), Dscore = c(-3.88097140918747, 
-1.61672655331958, -0.800904163207618, -1.63987714337736, -1.27356679469661, 
-0.123389213996389, -1.67470063459416, -1.53446926434865, 1.41432216204886, 
-2.93976791454954, -2.22110579039093, 0.179787740964598, -0.496345860693154, 
-2.25219836976259, 0.283128654684994, -1.02422222229106, -4.13093925848588, 
-2.00025863911258, -1.42277115507557, -2.20286053942706, -1.59680054370485, 
-4.67382100536604, -2.37506096226093, -2.8807566057491, -3.3382779475486, 
-1.64425464849276, -3.27011139841957, -3.69418205392501, -2.786090370905, 
-2.15312648161092, -2.03541950882678, -0.236513361147938, -1.080355218023, 
-0.744061467812739, -0.51452406800711, -2.13834789020542, 1.28548134814991, 
0.102783247605922, -8.60943620132279, 0.552638091261848, -2.6016685191023, 
-2.00359494680614, 1.09364751195267, 0.0228740916470703, -0.727749095761693, 
2.45361880473052, -0.700263607694208, 0.992436651274041, 5.55685390970607, 
0.0126595727091467, -0.885094834004169, 0.286395340453474, -0.674875047272186, 
-2.56290086784948, -1.6992770884242, 0.0858528219338089, -4.68307024987756, 
-7.19053429537607, -0.688092915132032, -1.90683437925634, -3.31079202975985, 
-2.00738870428399, -1.28966583325364, -1.35761860429989, -0.517228296926095, 
-2.49977175344713, 0.558525687352873, 0.855141372994123, -1.00932485695081
), Cank_Width_cm = c(0, 0, 0.09398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 2.90068, 0, 0, 0, 0, 0, 11.05916, 
33.24606, 0.1397, 0.7112, 2.54508, 2.06248, 0, 0.4572, 3.11404, 
0.86106, 0, 4.9784, 0, 0, 0, 0, 0, 0, 0, 3.27152, 0.09906, 0, 
0.78994, 0, 0, 0, 0, 0, 0.61722, 29.5402, 0, 1.88722, 0, 0.08382, 
2.43332, 0.25654, 0, 0.28956, 0, 0, 0.79756, 0), Canks_Per_Year = c(0, 
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 
0, 0, 0, 0, 0, 3, 11, 1, 2, 3, 3, 0, 1, 4, 1, 0, 5, 0, 0, 0, 
0, 0, 0, 0, 4, 1, 0, 1, 0, 0, 0, 0, 0, 2, 17, 0, 5, 0, 1, 6, 
1, 0, 1, 0, 0, 2, 0)), .Names = c("Year", "Unique_ID_Tree", "Dscore", 
"Cank_Width_cm", "Canks_Per_Year"), row.names = c(333L, 340L, 
344L, 345L, 352L, 356L, 357L, 364L, 368L, 369L, 376L, 380L, 381L, 
388L, 392L, 393L, 400L, 404L, 405L, 412L, 416L, 417L, 424L, 428L, 
429L, 436L, 440L, 441L, 448L, 452L, 453L, 460L, 464L, 465L, 472L, 
476L, 477L, 484L, 488L, 489L, 496L, 500L, 501L, 508L, 512L, 513L, 
520L, 524L, 525L, 532L, 536L, 537L, 544L, 548L, 549L, 556L, 560L, 
561L, 568L, 572L, 573L, 580L, 584L, 585L, 592L, 596L, 597L, 604L, 
608L), class = "data.frame")
KKL234
  • 367
  • 1
  • 5
  • 23
  • Imo, `p2` looks as it should using your data, `ggplot_dual_axis_facet` is not given. I'm using `packageVersion("ggplot2")` `‘2.2.1.9000’` – lukeA Sep 05 '17 at 21:06
  • @lukeA I edited the question and added the ggplot_dual_axis function (borrowed and edited from another question). – KKL234 Sep 05 '17 at 21:21
  • 1
    Since the function seems to cause the trouble, maybe fixate both limits? `xaxis <- list(scale_x_continuous(limits = c(1950, 2010))); p <- ggplot_dual_axis_facet(p1+xaxis, p2+xaxis)` – lukeA Sep 05 '17 at 21:39
  • @lukeA thanks for the suggestion. Fixing the limits fixes problems 2 and 3, now I just have to tackle the bar width issue. Some of my bars, within the same facet, still have different widths. – KKL234 Sep 06 '17 at 04:39
  • I beliebe the bar width issue has to do with the image dimensions you chose and some rounding; but I dunno any rule to apply so that every bar gets exactly the same width in terms of pixels. (Imho I would not care about it.) – lukeA Sep 06 '17 at 08:14
  • The different bar widths is likely due to dodging (so you plot >1 y value at an x value). See `position_dodge2` in the development version of *ggplot2* or do something along the lines of the answer to [this question](https://stackoverflow.com/questions/46048925/bars-in-geom-bar-are-not-of-equal-width). – aosmith Sep 06 '17 at 15:56

0 Answers0