Calculate XY polar coordinates to place an object right below a value label
Asked Answered
P

3

5

Consider the following dataset:

ig_5 <- data.frame(
  category = c("A", "B", "C", "D", "E", "F"),
  prop = c(0.1, 0.2, 0.15, 0.25, 0.05, 0.25)
) %>%
  mutate(lab.ypos = cumsum(prop) - 0.5*prop)

I created a donut chart with the following code:

ggplot(ig_5, aes(x = 2, y = prop, fill = prop)) +
  geom_bar(stat = "identity", color = "white") +
  coord_polar(theta = "y", start = 0) +
  geom_text(aes(y = lab.ypos, label = prop), color = "black", size = 5) +
  xlim(.5, 2.5)

As it can be seen, the value labels are placed in the middle of each category. Now, I need to place figures rigth below each of the value labels. I can't just paste the new object to the value because the colors of the text and the figure are different. Therefore, I imagined that there should be a way to use the the coordinates of the value labels (x = 2, y= lab.ypos = cumsum(prop) - 0.5*prop) to position the figures as I need.

I added the new figure with geom_label and gave it a position that is proportional to the XY coordinates of the value labels. However, I haven't suceeded. This is an example of what I have tried.

ig_5 <- data.frame(
  category = c("A", "B", "C", "D", "E", "F"),
  prop = c(0.1, 0.2, 0.15, 0.25, 0.05, 0.25)) %>%
  mutate(lab.ypos = cumsum(prop) - 0.5*prop, 
         lab.ypos2 = cumsum(prop) + 0.3*prop)

 
ggplot(ig_5, aes(x = 2, y = prop, fill = prop)) +
  geom_bar(stat = "identity", color = "white") +
  coord_polar(theta = "y", start = 0) +
  geom_text(aes(y = lab.ypos, label = prop), color = "black", size = 5) +
  geom_label(aes(y = lab.ypos,
                 x = c(1.85, 2.1, 2.2, 1.95, 1.8, 1.85),
                 label = "figure"), 
             color = 'red') +
  xlim(.5, 2.5) 

And the result I obtained:

Result

Pierian answered 9/5, 2023 at 21:39 Comment(1)
What a nice and reproducible first question! Welcome to the site!Jarodjarosite
J
3

We can abuse vjust to vertically justify the label beyond the normal 0 to 1 range. This will visually move the label vertically regardless of the coordinate system. The amount that will work will likely depend on the dimensions of the output - just try values until it works :)

ggplot(ig_5, aes(x = 2, y = prop, fill = prop)) +
  geom_bar(stat = "identity", color = "white") +
  coord_polar(theta = "y", start = 0) +
  geom_text(aes(y = lab.ypos, label = prop), color = "black", size = 5) +
  geom_label(aes(y = lab.ypos,
                 label = "figure"), 
             vjust = 1.5,
             color = 'red') +
  xlim(.5, 2.5)

enter image description here

Jarodjarosite answered 9/5, 2023 at 21:55 Comment(0)
C
4

I'm a bit biased, but I think geomtextpath works well here:

library(geomtextpath)

ggplot(ig_5, aes(x = 2, y = prop, fill = prop)) +
  geom_bar(stat = "identity", color = "white", linewidth = 1.5) +
  coord_polar(theta = "y", start = 0) +
  geom_textpath(aes(y = lab.ypos, label = prop, group = category), 
                color = "black", size = 8, angle = 90, vjust = 1) +
  geom_labelpath(aes(y = lab.ypos, label = "figure", group = category), 
                color = "red4", size = 6, angle = 90, vjust = -1.5) +
  scale_fill_gradientn(colours = c("lightyellow", "gold", "orange")) +
  xlim(.5, 2.5) +
  theme_void(base_size = 20)

enter image description here

Camp answered 9/5, 2023 at 23:9 Comment(0)
J
3

We can abuse vjust to vertically justify the label beyond the normal 0 to 1 range. This will visually move the label vertically regardless of the coordinate system. The amount that will work will likely depend on the dimensions of the output - just try values until it works :)

ggplot(ig_5, aes(x = 2, y = prop, fill = prop)) +
  geom_bar(stat = "identity", color = "white") +
  coord_polar(theta = "y", start = 0) +
  geom_text(aes(y = lab.ypos, label = prop), color = "black", size = 5) +
  geom_label(aes(y = lab.ypos,
                 label = "figure"), 
             vjust = 1.5,
             color = 'red') +
  xlim(.5, 2.5)

enter image description here

Jarodjarosite answered 9/5, 2023 at 21:55 Comment(0)
C
3

Another option would be to use ggtext::geom_richtext which via the label.margin argument allows to "shift" the label by half the size of the value labels which together with using vjust = 1 will or should ensure that the labels are placed straight below the value labels.

library(ggplot2)

ggplot(ig_5, aes(x = 2, y = prop, fill = prop)) +
  geom_bar(stat = "identity", color = "white") +
  coord_polar(theta = "y", start = 0) +
  geom_text(aes(y = lab.ypos, label = prop),
    color = "black", size = 5
  ) +
  ggtext::geom_richtext(
    aes(
      y = lab.ypos,
      label = "figure"
    ),
    color = "red",
    label.margin = unit(2.5, "mm"),
    vjust = 1
  ) +
  xlim(.5, 2.5)

enter image description here

Cancel answered 9/5, 2023 at 22:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.