3

I want to layer something specifically on one of the dodged bars, how would I be able to do that?

In the below example, I want to layer something specifically on A3 in the cat3 group on the barplot. I know that x = 3 for cat3 but because of the interdependence of the widths for dodge and bar width it seems difficult to target that one bar. Is there any formula that i can use to calculate the x coordinate? I have provided an example code below. thanks

x1 <- c(15,75,28,60,80,100)
x2 <- c('cat1','cat2','cat3','cat1','cat2','cat3')
x3 <- c('A1','A2','A3','A4','A1','A2')
data=data.frame(cbind(x1,x2,x3),stringsAsFactors = F)
data$x1 <- as.numeric(data$x1)
data$x2 <- factor(data$x2)
data$x3 <- factor(data$x3)

ggplot(data,aes(y = x1, x = x2)) + geom_bar(stat = 'identity', 
                                 aes(fill = data$x3, width = 0.5), 
                                 position = position_dodge(width = 0.8))

Bar plot

StatMan
  • 135
  • 8
  • 2
    They are in plot units (at least bar width). A `geom_bar` width of 1 will have the bars touching, and everything is relative to that. By the way, **never** use `data$column` inside `aes()` - it will override the data argument and cause problems if you facet or use more complicated stats. You should have `fill = x3` not `fill = data$x3`. – Gregor Thomas Nov 23 '15 at 18:27

1 Answers1

6

The width argument in position_dodge() is specifying the distance between the leftmost edge of the left bar and the rightmost edge of the right bar. With a dodge width of 0.8, the distance between your start point of x = 3 for your x3 category and the edge of either bar is 0.4 (+0.4 on the right and -0.4 on the left) Half of 0.4 (i.e. 0.2) will bring you to midpoint of the bar (again +0.2 on the right and -0.2 on the left). This is true irrespective of the bar width.

Here's an example where I've drawn an H on the right bar in cat3. The y-units line up with those on the y-axis.

ggplot(data,aes(y = x1, x = x2)) + 
    geom_bar(stat = 'identity',
             aes(fill = x3, width = 0.5), 
             position = position_dodge(width = 0.8))+
    geom_text(aes(x = 3.2, y = 25, label = "H"), size = 10)

UpdatedImageWithLetterH

tsurudak
  • 602
  • 7
  • 14
  • Amazing. That works great to find the center of A3 for cat3. Is there a way to target the leftmost edge of A3 though? I guess this might be dependent on the barwidth as well? – StatMan Nov 25 '15 at 02:45
  • I made two new variables, `w = 0.5` and `dodgew = 0.8`, then replaced the last line of the graph code with the following: `geom_text(aes(x = (3+(dodgew/2)-(w/2)), y = 25, label = "0"), size = 10)`. (You'll need to update the width and dodge width parameters in your graph call too) This seems to get pretty close to the left edge. It turns out there is actually a bit of buffer space on either side of the bars in the position_dodge() width argument so my initial answer is a bit flawed. I will investigate and fix. – tsurudak Nov 25 '15 at 12:51
  • 1
    @tsurudak "The `width` argument in `position_dodge()` is specifying the distance between the leftmost edge of the left bar and the rightmost edge of the right bar.". I don't think this is entirely correct. Please see [this Q&A](http://stackoverflow.com/questions/34889766/what-is-the-width-argument-in-position-dodge/35102486#35102486) – Henrik Jan 31 '16 at 09:01