Indrajeet Patil
Indrajeet Patil

Reputation: 4889

centering the label segment starting points for labelled pie charts

I am trying to create a labelled pie chart using ggrepel based on a StackOverflow answer, but I can't seem to get the position of the labels correctly.

Ideally, I would like the segments that connect the labels to the portion of the pies to start in the middle of the pie for it to be more aesthetically pleasing. But this is not what I get, and I am not sure what I should be changing. I have tried setting position = ggplot2::position_fill(vjust = 0.5) in ggrepel call, but that doesn't help either.

data

# setup
set.seed(123)
library(ggplot2)
library(ggrepel)
library(forcats)

# data
(df <- structure(
  list(
    cyl = structure(
      c(1L, 3L, 2L),
      .Label = c("8", "6", "4"),
      class = "factor"
    ),
    counts = c(14L, 11L, 7L),
    perc = c(43.75, 34.375, 21.875),
    label = c("44%", "34%", "22%")
  ),
  row.names = c(NA, -3L),
  class = c("tbl_df", "tbl", "data.frame")
))
#> # A tibble: 3 x 4
#>   cyl   counts  perc label
#>   <fct>  <int> <dbl> <chr>
#> 1 8         14  43.8 44%  
#> 2 4         11  34.4 34%  
#> 3 6          7  21.9 22%

function

# function
foo <- function(df, x) {
  ggplot2::ggplot(
    data = df,
    mapping = ggplot2::aes(x = "", y = counts, fill = forcats::fct_inorder({{ x }}))
  ) +
    ggplot2::geom_bar(
      stat = "identity",
      color = "black",
      width = 1,
      na.rm = TRUE
    ) +
    coord_polar("y", start = 0) +
    ggrepel::geom_label_repel(
      aes(label = label),
      show.legend = FALSE,
      nudge_x = 1
    ) +
    guides(fill = guide_legend(title = rlang::as_name(rlang::ensym(x))))
}

plot

# plot
foo(df, cyl)

plot

Upvotes: 2

Views: 240

Answers (1)

Z.Lin
Z.Lin

Reputation: 29095

You can calculate the labels' stacked positions manually, instead of relying on ggplot. See if the following works for you:

foo <- function(df, x) {
  df$y.label <- 0.5 * df$counts + rev(cumsum(dplyr::lag(rev(df$counts), default = 0)))
  ggplot2::ggplot(
    data = df,
    mapping = ggplot2::aes(x = "", y = counts, fill = forcats::fct_inorder({{ x }}))
  ) +
    ggplot2::geom_col(
      color = "black",
      width = 1,
      na.rm = TRUE
    ) +
    coord_polar("y", start = 0) +
    ggrepel::geom_label_repel(
      aes(label = label, y = y.label),
      show.legend = FALSE,
      nudge_x = 1
    ) +
    guides(fill = guide_legend(title = rlang::as_name(rlang::ensym(x))))
}

foo(df, cyl)

plot

Upvotes: 1

Related Questions