11

I saw this answer but couldn't replicate it.

I get my data like this:

df = data.frame(x = rep(sample(letters, 4), 2), 
                y = round(runif(8,1,100),0), 
                z = c(rep("group1",4), rep("group2",4)))

# I then add a 'percent' column like so:

df$perc[1:4] = df$y[1:4] / sum(df$y[1:4])
df$perc[5:8] = df$y[5:8] / sum(df$y[5:8])

# Which I then convert like so:
df$perc = paste(round(df$perc * 100, 1), "%", sep="")

# The ggplot:
library(ggplot2)

ggplot(df) + 
geom_bar(aes(z, y, fill=x), position="dodge", stat="identity") + 
geom_text(aes(z,y,label=perc), position=position_dodge(width=1), size=4)

Result:

enter image description here

I can't figure out what I did wrong.

Community
  • 1
  • 1
knl
  • 377
  • 2
  • 3
  • 9
  • Does this answer your question? [Position geom\_text on dodged barplot](https://stackoverflow.com/questions/6017460/position-geom-text-on-dodged-barplot) – camille Oct 12 '21 at 14:43

1 Answers1

26

Just one minor change solves the issue. You need to specify group=x inside your geom_text(aes(...)) call.

ggplot(df) + 
geom_bar(aes(z, y, fill=x), position=position_dodge(width=1), stat="identity") + 
geom_text(aes(z,y,label=perc, group=x), position=position_dodge(width=1), size=4)

enter image description here

bdemarest
  • 14,397
  • 3
  • 53
  • 56
  • 2
    Or move the `fill = x` to the 'top level' in `ggplot`. Then this dodging variable is inherited also to `geom_text`. `dodge <- position_dodge(width = 1)`; `ggplot(df, aes(z, y, fill = x, label = perc)) + geom_bar(position = dodge, stat = "identity") + geom_text(position = dodge, size = 4)`. You also avoid repeating the `aes(z, y,` for each `geom`. – Henrik Jun 04 '15 at 07:08