detraveller
detraveller

Reputation: 295

Conditional vjust for barplot labels in R ggplot2

I have an excel file with data about the genders of different people. I am reading it with read.csv. I am using ggplot to plot a barplot of that data.

THis is the data:

> dput(dat.absolventen$Geschlecht)
structure(c(1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 
1L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("männlich", 
"weiblich"), class = "factor")

And this is my code:

ggplot(data = d, aes(x=Geschlecht,y=(..count..)/sum(..count..))) +
  geom_bar(
            fill="steelblue"
           ) +
  geom_text(aes(label = sprintf("%0.1f%%",(..count..)/sum(..count..)*100)), 
            stat = "count", 
            colour = "white",
            vjust = +2,
            fontface = "bold"               
            )

This gives me a good enough graph. There are 9 females and 32 males. I can get it to show me the percentages inside each bar. However, I would like to show the percentage of the males inside the bar and the percentage of females outside or not top of the bar(basically if the bar is too short, move the label outside).

I know I can use ifelse() but I can't figure out how to use it for each value, that is, the total count of male and female. If I use ifelse() when defining aes(label =...) then the criteria is applied on the whole column. I want it to test each bar, that is, male and female, and then vjust it according to the criteria of less than or greater than, say, 15.

I have tried using

ifelse(..count.. >15, -2, +2)

but this gives me the error that '..count.. not found'. And I am not sure why it says that because while defining aesthetics I am using ..count.. and it works there.

There have been many similar questions asked before but I have been unable to get any help from them, which is why I have to ask again for this particular case. Regards.

Upvotes: 0

Views: 1215

Answers (1)

Joseph Clark McIntyre
Joseph Clark McIntyre

Reputation: 1094

This issue, I think, is that you can only access ..count.. inside aes(). You can't pass that to vjust because it's not defined. Here is a hacky solution. Basically, I figure out the adjustment outside of ggplot based on a table of the grouping factor, call that adj, and give that info to ggplot.

vec <- structure(c(1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 
            1L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
            1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("männlich", 
                                                                        "weiblich"), class = "factor")

d <- data.frame(gender = vec)

nums <- table(d)
adj <- ifelse(nums > 15, 2, -2)

ggplot(data = d, aes(x=gender,y=(..count..)/sum(..count..))) +
  geom_bar(
    fill="steelblue"
  ) +
  geom_text(aes(label = sprintf("%0.1f%%",(..count..)/sum(..count..)*100)), 
            stat = "count", 
            colour = "black",
            vjust = adj,
            fontface = "bold"               
  )

Upvotes: 2

Related Questions