Geom_label conditional change color text and padding

75 Views Asked by At

I am creating a pie chart and I would like the color of the label text and padding to be white when the segment being labelled is filled with black. At the moment other labels follow the color of the segment labelled and I want to keep it so. The black filled segments also have black label text and can therefore not be seen, despite being there.

ggplot(pigs2.proportions,
       aes(x="", y=comp_percent, fill = percent_class, width = 0.4)) +
  geom_bar(stat="identity") +
  geom_label(
    aes(
      label = ifelse(comp_percent %% 1 != 0, sprintf("%.2f%%", comp_percent),
                     sprintf("%.0f%%", comp_percent))),
            position = position_stack(vjust = 0.5), 
    size = 4,
    label.padding = unit(0.25, "lines"),
    show.legend = FALSE) +
  coord_polar("y", start=0) +
  facet_wrap(~factor(source, levels = c("fish", "soy", "skim")), labeller = custom_labeller("source")) +
  scale_fill_manual(values = c("low" = "black", "moderate" = "darkgray", "high" = "lightgray")) +
  theme(
    axis.text.x = element_blank(), # Hide labels on polar coordinate axis
    panel.grid = element_blank(),  # Remove grid lines
    panel.border = element_blank(),  # Remove round outline
    axis.text = element_blank(),  # Remove axis text
    axis.title = element_blank()  # Remove axis titles
  )
structure(list(source = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 
3L, 3L), levels = c("fish", "soy", "skim"), class = "factor"), 
    percent_class = structure(c(3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 
    2L), levels = c("low", "moderate", "high"), class = "factor"), 
    count = c(3L, 2L, 5L, 1L, 3L, 6L, 1L, 3L, 5L), comp_percent = c(30, 
    20, 50, 10, 30, 60, 11.1111111111111, 33.3333333333333, 55.5555555555556
    ), pos = c(15, 10, 25, 35, 35, 80, 45.5555555555556, 66.6666666666667, 
    137.777777777778)), class = c("grouped_df", "tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -9L), groups = structure(list(
    percent_class = structure(1:3, levels = c("low", "moderate", 
    "high"), class = "factor"), .rows = structure(list(c(2L, 
    5L, 8L), c(3L, 6L, 9L), c(1L, 4L, 7L)), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -3L), .drop = TRUE))

output from code

1

There are 1 best solutions below

0
stefan On BEST ANSWER

As suggested by @AllanCameron in the comments you could e.g. map the condition percent_class == "low" on the color aes and set your desired text colors using scale_color_manual. However, doing so changes the grouping of the data for geom_label and hence the stacking of the labels no longer aligns with the bars. To fix that you have to explicitly map percent_class on the group aes.

library(ggplot2)

p <- ggplot(
  pigs2.proportions,
  aes(x = "", y = comp_percent, fill = percent_class, width = 0.4)
) +
  geom_bar(stat = "identity") +
  coord_polar("y", start = 0) +
  facet_wrap(
    ~ factor(source, levels = c("fish", "soy", "skim")),
    # labeller = custom_labeller("source")
  ) +
  scale_fill_manual(
    values = c("low" = "black", "moderate" = "darkgray", "high" = "lightgray")
  ) +
  theme(
    axis.text.x = element_blank(), # Hide labels on polar coordinate axis
    panel.grid = element_blank(), # Remove grid lines
    panel.border = element_blank(), # Remove round outline
    axis.text = element_blank(), # Remove axis text
    axis.title = element_blank() # Remove axis titles
  )

p +
  geom_label(
    aes(
      label = ifelse(comp_percent %% 1 != 0,
        sprintf("%.2f%%", comp_percent),
        sprintf("%.0f%%", comp_percent)
      ),
      color = percent_class == "low",
      group = percent_class
    ),
    position = position_stack(vjust = 0.5),
    size = 4,
    label.padding = unit(0.25, "lines"),
    show.legend = FALSE
  ) +
  scale_color_manual(values = c("black", "white"))

A second option would be to use after_scale to conditionally set the color based on the value of fill like so:

p +
  geom_label(
    aes(
      label = ifelse(comp_percent %% 1 != 0,
        sprintf("%.2f%%", comp_percent),
        sprintf("%.0f%%", comp_percent)
      ),
      color = after_scale(
        ifelse(fill == "black", "white", "black")
      )
    ),
    position = position_stack(vjust = 0.5),
    size = 4,
    label.padding = unit(0.25, "lines"),
    show.legend = FALSE
  )