motabe
motabe

Reputation: 111

How to apply position_dodge to geom_point and geom_text in the same plot?

I woul like to be able to make the geom_text inside the geom_point to follow the re-positioning when applying position_dodge. That is, I would like to go from the code below:

Q <- as_tibble(data.frame(series = rep(c("diax","diay"),3),
                          value = c(3.25,3.30,3.31,3.36,3.38,3.42),
                          year = c(2018,2018,2019,2019,2020,2020))) %>%
  select(year, series, value)

ggplot(data = Q, mapping = aes(x = year, y = value, color = series, label = sprintf("%.2f",value))) +
  geom_point(size = 13) +
  geom_text(vjust = 0.4,color = "white", size = 4, fontface = "bold", show.legend = FALSE) 

which produces the following chart:

enter image description here

to the following change:

ggplot(data = Q, mapping = aes(x = year, y = value, color = series, label = sprintf("%.2f",value))) +
  geom_point(size = 13, position = position_dodge(width = 1)) +
  geom_text(position = position_dodge(width = 1), vjust = 0.4,
            color = "white", size = 4, fontface = "bold",
            show.legend = FALSE)

which produces the following chart:

enter image description here

The curious thing about this is the fact that excatly the same change works just fine if I change from geom_point to geom_bar:

ggplot(Q, aes(year, value, fill = factor(series), label = sprintf("%.2f",value))) +
  geom_bar(stat = "identity", position = position_dodge(width = 1)) + 
  geom_text(color = "black", size = 4,fontface= "bold",
            position = position_dodge(width = 1), vjust = 0.4, show.legend = FALSE) 

Upvotes: 2

Views: 5768

Answers (2)

jazzurro
jazzurro

Reputation: 23574

One patch work would be the following. Since you cannot add labels on top of the data point using geom_text() right away, you may want to go round a bit. I first created a temporary graphic with geom_point(). Then, I accessed to the data frame which is used for drawing the graphic. You can find the values of x and y axis. Using them, I created a new data frame called temp which include the axis information and the label information. Once I had this data frame, I could draw the expected outcome using temp. Make sure that you use inherit.aes = FALSE in geom_text() since you are using another data frame.

library(dplyr)
library(ggplot2)

g <- ggplot(data = Q, aes(x = year, y = value, color = series)) +
     geom_point(size = 13, position = position_dodge(width = 1))

temp <- as.data.frame(ggplot_build(g)$data) %>%
        select(x, y) %>%
        arrange(x) %>%
        mutate(label = sprintf("%.2f",Q$value))

ggplot(data = Q, aes(x = year, y = value, color = series)) +
geom_point(size = 13, position = position_dodge(width = 1)) +
geom_text(data = temp, aes(x = x, y = y, label = label), 
          color = "white", inherit.aes = FALSE)

enter image description here

Upvotes: -1

Axeman
Axeman

Reputation: 35262

This happens because the the dodging is based on the group aesthetic, automatically set in this case to series because of the mapping to color. The issue is that the text layer has it's own color ("white") and so the grouping is dropped. Manually set the grouping, and all is good:

ggplot(Q, aes(x = year, y = value, color = series, label = sprintf("%.2f",value), group = series)) +
    geom_point(size = 13, position = position_dodge(width = 1)) +
    geom_text(position = position_dodge(width = 1), vjust = 0.4, color = "white", size = 4, 
              fontface = "bold", show.legend = FALSE)

enter image description here

Upvotes: 3

Related Questions