Home > Back-end >  ggplot2 pie chart : Repositioning ggrepel slice labels by moving them toward circumference of the pi
ggplot2 pie chart : Repositioning ggrepel slice labels by moving them toward circumference of the pi

Time:03-12

I am trying to create a pie chart of a following data.table obj by using ggplot2;

> pietable
                       cluster N P p
     1:                      1 962 17.4  8.70
     2:                      3 611 11.1 22.95
     3:                     10 343  6.2 31.60
     4:                     12 306  5.5 37.45
     5:                      8 290  5.2 42.80
     6:                      5 288  5.2 48.00
     7:                      7 259  4.7 52.95
     8:                     18 210  3.8 57.20
     9:                      4 207  3.7 60.95
    10:                      9 204  3.7 64.65
    11:                     16 199  3.6 68.30
    12:                     17 201  3.6 71.90
    13:                     14 174  3.1 75.25
    14:                     22 159  2.9 78.25
    15:                      6 121  2.2 80.80
    16:                     21 106  1.9 82.85
    17:                      2 101  1.8 84.70
    18:                     26  95  1.7 86.45
    19:                     11  89  1.6 88.10
    20:                     24  84  1.5 89.65
    21:                     32  71  1.3 91.05
    22:                     13  65  1.2 92.30
    23:                     38  50  0.9 93.35
    24:                     25  41  0.7 94.15
    25:                     36  36  0.7 94.85
    26:                     20  39  0.7 95.55
    27:                     28  33  0.6 96.20
    28:                     23  30  0.5 96.75
    29:                     31  24  0.4 97.20
    30:                     15  21  0.4 97.60
    31:                     34  22  0.4 98.00
    32:                     30  14  0.3 98.35
    33:                     33  19  0.3 98.65
    34:                     40  10  0.2 98.90
    35:                     29  11  0.2 99.10
    36:                     37   9  0.2 99.30
    37:                     19   8  0.1 99.45
    38:                     27   6  0.1 99.55
    39:                     39   6  0.1 99.65
    40:                     35   3  0.1 99.75

N is a total count of a particular cluster, P is a proportion , and p is a cumsum of P.

A ggplot2 line to create the pie chart is as follows;

ggplot(pietable, aes("", P))   
  geom_bar(
    stat = "identity", 
    aes(
      fill = rev(fct_inorder(cluster))))  
  geom_label_repel(
    data = pietable[!P<1], 
    aes(
      label = paste0(P, "%"),
      y = p1,
      #col = rev(fct_inorder(cluster))
    ),
    point.padding = NA,
    max.overlaps = Inf,
    nudge_x = 1,
    color="red",
    force = 0.5,
    force_pull = 0,
    segment.alpha=0.5,
    arrow=arrow(length = unit(0.05, "inches"),ends = "last", type = "open"),
    show.legend = F
  )   
  geom_label_repel(
    data = pietable[!P<1], 
      aes(label = cluster,
      y = p1),
      size=2,  
      col="black",
      force = 0,
      force_pull = 0,
      label.size = 0.01,
      show.legend = F
    ) 
  scale_fill_manual(values = P40)   
  coord_polar(theta = "y") 
  theme_void()

This generates a pie chart like this;

enter image description here

Some of the pie slices with extremely small values are not labeled for an obvious reason.

What I'd like to do is to reposition slice labels (in number) by moving them toward circumference of the pie.

An example of the pie chart that I'd like to create looks like this;

enter image description here

I'd appreciate any suggestions to accomplish this.

CodePudding user response:

This is a lot of labeling for one visualization, and you may want to consider a different design.

That said, you can add nudge_x = 0.33 and segment.color = 'transparent' to the relevant geom to adjust the positioning of the labels. Note that in order to make the red arrows align to the nudged black labels, you have to add aes(after_stat(1.33)) to the red geom, matching the new nudge_x parameter of the black geom ( 1.0). These lines are marked with # added comments in the code below.

I've made some light modifications to your plotting code (you seem to have variables in your workspace that are not available in your post), but this is the general idea:

ggplot(pietable, aes("", P))   
  geom_bar(
    stat = "identity", 
    aes(
      fill = factor(cluster)))  
  geom_label_repel(
    data = pietable[!pietable$P<1, ], 
    aes(
      label = paste0(P, "%"),
      y = p,
      x = after_stat(1.33) # added
      #col = rev(fct_inorder(cluster))
    ),
    point.padding = NA,
    max.overlaps = Inf,
    nudge_x = 1,
    color="red",
    force = 0.5,
    force_pull = 0,
    segment.alpha=0.5,
    arrow=arrow(length = unit(0.05, "inches"),ends = "last", type = "open"),
    show.legend = F
  )   
  geom_label_repel(
    data = pietable[!pietable$P<1,], 
    aes(label = cluster,
        y = p),
    size=2,  
    col="black",
    nudge_x = 0.33, # added
    force = 0,
    force_pull = 0,
    label.size = 0.01,
    show.legend = F,
    segment.color = 'transparent' # added
  ) 
  coord_polar(theta = "y") 
  theme_void()

enter image description here

And for reference, the data set I worked from:

pietable <- structure(list(cluster = c(1, 3, 10, 12, 8, 5, 7, 18, 4, 9, 16, 
17, 14, 22, 6, 21, 2, 26, 11, 24, 32, 13, 38, 25, 36, 20, 28, 
23, 31, 15, 34, 30, 33, 40, 29, 37, 19, 27, 39, 35), N = c(962, 
611, 343, 306, 290, 288, 259, 210, 207, 204, 199, 201, 174, 159, 
121, 106, 101, 95, 89, 84, 71, 65, 50, 41, 36, 39, 33, 30, 24, 
21, 22, 14, 19, 10, 11, 9, 8, 6, 6, 3), P = c(17.4, 11.1, 6.2, 
5.5, 5.2, 5.2, 4.7, 3.8, 3.7, 3.7, 3.6, 3.6, 3.1, 2.9, 2.2, 1.9, 
1.8, 1.7, 1.6, 1.5, 1.3, 1.2, 0.9, 0.7, 0.7, 0.7, 0.6, 0.5, 0.4, 
0.4, 0.4, 0.3, 0.3, 0.2, 0.2, 0.2, 0.1, 0.1, 0.1, 0.1), p = c(8.7, 
22.95, 31.6, 37.45, 42.8, 48, 52.95, 57.2, 60.95, 64.65, 68.3, 
71.9, 75.25, 78.25, 80.8, 82.85, 84.7, 86.45, 88.1, 89.65, 91.05, 
92.3, 93.35, 94.15, 94.85, 95.55, 96.2, 96.75, 97.2, 97.6, 98, 
98.35, 98.65, 98.9, 99.1, 99.3, 99.45, 99.55, 99.65, 99.75)), row.names = c(NA, 
-40L), class = c("tbl_df", "tbl", "data.frame"))
  • Related