2

I want to add text (n) on each bar in a horizontal bar plot in ggplot environment, but keep getting error message, I wonder what will be correct way to do so? Also, I tried to invoke viridis package to add color on those bars but can't seem to get around. Is there any way to map different colors to those bars?

My current code is shown at below.

    # the data

    city_r <- data.frame(
    City = c("A", "B", "C", "D", "E", "F"),
    rating = c(5.52, 8, 6.24, 5.89, 5.57, 8.67),
    n = c(112, 1, 25, 40, 9, 36)
                     )
    # rating means mayor's rating
    # n means respondents' size in each city

    library(ggplot2)

    # plot it
    g <- city_r %>% 
      group_by(City) %>% 
      arrange(rating) %>% 
      ggplot(., mapping = aes(x=reorder(City, rating), y =rating))+
      geom_text(aes(n), colour = "black", position = "dodge") +
      geom_bar(stat = "identity", width=.8, position = position_dodge(width = .25))+
      labs(
        title = "",
        y = "Mayor's rating",
        x = ""
      )+
      coord_flip()
      
     g
      

1 Answer 1

6

I'm assuming your error is

Error: Discrete value supplied to continuous scale

This is because your geom_text is using aes(n), where the default first-arg of aes is x=, not what I think you intend, label=.

Fixing that and adding hjust=-0.5 (for an offset), then we can add aes(fill=City) to the bars in order to start the colors, then add the scale itself.

g <- city_r %>% 
  group_by(City) %>% 
  arrange(rating) %>% 
  ggplot(., mapping = aes(x=reorder(City, rating), y =rating))+
  geom_text(aes(label=n), hjust=-0.5, colour = "black", position = "dodge") +
  geom_bar(aes(fill=City), stat = "identity", width=.8, position = position_dodge(width = .25))+
  labs(
    title = "",
    y = "Mayor's rating",
    x = ""
  )+
  coord_flip() +
  viridis::scale_fill_viridis(discrete=TRUE)
g
# Warning: Width not defined. Set with `position_dodge(width = ?)`

enter image description here


Edit

  • To remove the legend, add guide=NULL to the scale.
  • To move the numbers to the middle of the bars, you need to both (a) add a new y= aesthetic to geom_text, and change the order of geoms (since if the bars are added second, then they will completely obscure the numbers).

New code:

g <- city_r %>% 
#   group_by(City) %>% 
#   arrange(rating) %>% 
#   ggplot(., mapping = aes(x=reorder(City, rating), y =rating))+
#   geom_bar(aes(fill=City), stat = "identity", width=.8, position = position_dodge(width = .25))+
#   geom_text(aes(label=n, y=rating/2), hjust=-0.5, colour = "black", position = "dodge") +
#   labs(
#     title = "",
#     y = "Mayor's rating",
#     x = ""
#   ) +
#   coord_flip() +
#   viridis::scale_fill_viridis(guide=NULL, discrete=TRUE)
g
# Warning: Width not defined. Set with `position_dodge(width = ?)`

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Many thanks for your reply, is there a way to remove that vertical factor bar on the right? Also, I want to put those numbers in the middle of the bar, so that the right side of the plot won't get too congested.
Removing the legend is pretty simple, plenty of questions on SO cover that (I'm not at my computer so cannot test). The y aesthetic is inherited from the original call, your can override it by using something like aes(label=n, y=rating/2).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.