Search code examples
rggplot2positiongeom-text

Why is there one misplaced geom_text label in my stacked bar chart?


dataframe looks like this

focus_graph <- structure(list(question = c("Coherence: The lesson intentionally\nconnects mathematical concepts\nwithin and/or across grades\nas appropriate, reflecting the\ncoherence in the standards.", 
"A. Overall", "Rigor: The lesson intentionally\ntargets the aspect(s) of rigor\n(conceptual understanding,\nprocedural skill and fluency,\napplication) called for by the\nstandard(s) being addressed.", 
"Focus: The lesson focuses on the\ndepth of the grade/course-level\ncluster(s), grade/course-level\ncontent standard(s), or part(s)\nthereof", 
"Focus: The lesson focuses on the\ndepth of the grade/course-level\ncluster(s), grade/course-level\ncontent standard(s), or part(s)\nthereof", 
"A. Overall", "Rigor: The lesson intentionally\ntargets the aspect(s) of rigor\n(conceptual understanding,\nprocedural skill and fluency,\napplication) called for by the\nstandard(s) being addressed.", 
"Coherence: The lesson intentionally\nconnects mathematical concepts\nwithin and/or across grades\nas appropriate, reflecting the\ncoherence in the standards.", 
"Coherence: The lesson intentionally\nconnects mathematical concepts\nwithin and/or across grades\nas appropriate, reflecting the\ncoherence in the standards.", 
"Focus: The lesson focuses on the\ndepth of the grade/course-level\ncluster(s), grade/course-level\ncontent standard(s), or part(s)\nthereof", 
"A. Overall", "Rigor: The lesson intentionally\ntargets the aspect(s) of rigor\n(conceptual understanding,\nprocedural skill and fluency,\napplication) called for by the\nstandard(s) being addressed."
), response = structure(c(1L, 1L, 1L, 1L, 3L, 2L, 2L, 3L, 2L, 
2L, 3L, 3L), levels = c("Not Yet", "In Process", "Established"
), class = "factor"), n = c(6L, 5L, 5L, 4L, 3L, 2L, 2L, 1L, 1L, 
1L, 1L, 1L), percent = c(75, 62.5, 62.5, 50, 37.5, 25, 25, 12.5, 
12.5, 12.5, 12.5, 12.5), color = c("white", "white", "white", 
"white", "black", "black", "black", "black", "black", "black", 
"black", "black"), size = c(8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 
7)), row.names = c(NA, -12L), class = c("tbl_df", "tbl", "data.frame"
))

code looks like this:

library(tidyverse)
focus_graph |>
  ggplot(aes(x = question, y = percent)) +
  geom_col(aes(fill = response),
           position = ggplot2::position_stack(reverse = TRUE)
           ) +
  geom_text(aes(label = paste0(round(percent), "%\n(n = ", n, ")"), color = color, size = size), 
            position = position_stack(reverse = FALSE, vjust = 0.5),
            fontface = "bold",
            show.legend = FALSE) +
  scale_fill_manual(values = c("#040404", "#02587A", "#00ACF0")) +
  scale_color_identity() +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  scale_size_continuous(range = c(5, 10)) +
  coord_flip() +
  labs(x = "", y = "", title = stringr::str_wrap("High-Quality Mathematical Content: Does the content of the lesson reflect the key instructional shifts required by college and career ready mathematics standards?", width = 50)) +
  theme(legend.position = "bottom",
        legend.title = element_blank(),
        legend.text = element_text(size = 17),
        plot.title = element_text(face = "bold", size = 20),
        axis.text.y = element_text(size = 16, face = "bold"))

the resulting image has one misplaced geom_text that is not centered correctly, it weirdly includes the 38% and 12% in one part of the stacked bar, while all others are placed correctly.

I tried the code above and got the following image.

Chart which shows what I would want with arrows indicating correct placement on the incorrectly stacked text


Solution

  • I have resolved the issue, simply by adding the group = response parameter to the aes argument of geom_text, here is the final code.

    ggplot() +
        geom_col(aes(x = question, y = percent, fill = response),
          position = position_stack(vjust = 0.5, reverse = TRUE),
          alpha = 0.95
        ) +
        geom_text(aes(x = question, y = percent, label = paste0(round(percent), "%\n(n = ", n, ")"), color = color, size = size, group = response),
          position = position_stack(vjust = 0.5, reverse = TRUE),
          fontface = "bold",
          show.legend = FALSE
        ) +
        scale_fill_manual(values = tl_palette(color = "blue", n = unique_colors_n + 1, theme = "dark")[-1]) +
        scale_color_identity() +
        scale_y_continuous(labels = scales::percent_format(scale = 1)) +
        scale_size_continuous(range = c(5, 10)) +
        coord_flip() +
        labs(x = "", y = "", title = title) +
        theme_tl(legend = TRUE) +
        theme(
          legend.position = "bottom",
          legend.title = element_blank(),
          legend.text = element_text(size = 17),
          legend.key.width = unit(2, "cm"),
          legend.key.height = unit(1.5, "cm"),
          plot.title = element_text(face = "bold", size = 20),
          axis.text.y = element_text(size = 16, face = "bold")
        )