Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected behaviour in ggplot2 pie chart labeling

I have checked the other questions in here but I couldn't see this problem. I have a labeling problem. Weird thing is that code is working quite OK for all labels except for one. When I checked the data set (which is something really simple), everything seems quite fine (one column with factor variables, another with numerical).

It is weird because it works OK for some other data with the same structure. However, I tried/checked everything but couldn't solve this issue. Here is the problem:

library(ggplot2)
library(ggrepel)

df = data.frame(
  status = c("Oak", "maple", "walnut", "Pine"),
  value = c( 47.54, 37.70, 11.48, 3.28))

ggplot(df, aes(x = "" , y = value, fill = fct_inorder(status))) +
  geom_bar(width = 1, stat = "identity") +
  coord_polar(theta = "y", start = 0 ) +
  scale_fill_brewer(palette = "Set3", direction = -4) +
  geom_label_repel(aes(label = paste0(value, "%")), size=4, show.legend = F, nudge_x = 1) +
  guides(fill = guide_legend(title = "Status")) +
  theme_void()

One of the labels came up with an issue

It would be great if I have at least a suggestion to try or explanation of this weird behaviour.

Apparently, with the new ggplot2 update they figured the position problem out without giving any extra position data but somehow, If you are unable to use it because of technical limitations, this might help to solve this kind of issues.

like image 719
DSA Avatar asked Sep 10 '18 13:09

DSA


1 Answers

I think the problem is that the geom_bar (or better geom_col) defaults to position = stack whereas geom_text_repel doesn't. Setting geom_text_repel to position= "stack" puts the labels at the end of each section of the pie rather than the midpoint.

It is possible to pre-calculate the positions. The code below works for the data shown, but might not be general as it depends on the order of the rows.

library(ggplot2)
library(ggrepel)

df = data.frame(
  status = c("Oak", "maple", "walnut", "Pine"),
  value = c( 47.54, 37.70, 11.48, 3.28))

df2 <- df %>% 
  mutate(
    cs = rev(cumsum(rev(value))), 
    pos = value/2 + lead(cs, 1),
    pos = if_else(is.na(pos), value/2, pos))

ggplot(df, aes(x = "" , y = value, fill = fct_inorder(status))) +
  geom_col(width = 1) +
  coord_polar(theta = "y", start = 0 ) +
  scale_fill_brewer(palette = "Set3", direction = -4) +
  geom_label_repel(aes(y = pos, label = paste0(value, "%")), data = df2, size=4, show.legend = F, nudge_x = 1) +
  guides(fill = guide_legend(title = "Status")) +
  theme_void()
like image 86
Richard Telford Avatar answered Nov 04 '22 14:11

Richard Telford