rggplot2ggrepel

Stacked bar with labels at the right end using ggrepel and ggplot2?


I need a bar chart that shows different segments of a dataframe, including years, revenue sources, and revenue figures for a company. I can generate the chart, but there are issues with the labels. They are disorganized, not properly aligned with their respective segments, and don't have the same color as the corresponding segment.

I have tried using base R, but specially I have used ggrepel and the geom_text_repel function with ggplot2. The function seems to work but shows the wrong result.

type_vec <- c(rep("ecommerce",4),rep("third_party",4),rep("retail",4),rep("services",4),
              rep("marketplace",4))
year_vec <- rep(c("2010","2011","2013","2014"),5)
revenue_vec <- c(8709, 8773, 8974, 9876, 1772, 1891, 1915, 2872, 5727, 5820, 5904, 6500,
  1, 2, 3, 6, 4370, 4463, 4479, 4817)


data_raw <- tibble(year=year_vec,type=type_vec,revenue=revenue_vec)

data_df <- data_raw %>% 
  mutate(group = as.factor(if_else(revenue < 11, "other", type ))) %>% 
  mutate(group = fct_relevel(group, "other", after=Inf),
         label_type = if_else(year == 2014,type, NA_character_))

theme_stacked_bar <- function( ) {
  
  theme(
    legend.position = "none",
    plot.margin = unit(c(2,7,2,2),"cm"),
    axis.text = element_text(size=3)
  )
}
  
data_plot <- ggplot(
  data_df %>% filter(group != "other"), 
  aes(year, revenue, group = type)
) + 

  geom_bar(
    stat = "identity",
    data = data_df %>% filter(group == "other"),
    fill = "grey85",
    alpha = .5) +
  geom_bar(
    stat = "identity",
    aes(fill = group)) +
  scale_fill_brewer() +
  theme_stacked_bar()
data_plot


data_plot <- data_plot +
  geom_text_repel(
    aes(color = group, label = label_type ),
    # family = "Lato",
    # fontface = "bold",
    size = 8,
    direction = "y",
    xlim = c(2014.8, NA),
    hjust = 0,
    segment.size = .7,
    segment.alpha = .5,
    segment.linetype = "dotted",
    box.padding = .4,
    segment.curvature = -0.1,
    segment.ncp = 3,
    segment.angle = 20
  ) +

    coord_cartesian(
    clip = "off",
       ylim = c(0,25000)
      )

    data_plot

Expected

I want the labels aligned with the right segments , also i want the words to match the color palette used

stacked bar chart

Result

I got the stacked bar chart with the labels messy and wrong colors. I am unable to organize the labels and also I am unable to add the color of the color palette used in the bars.

stacked bar chart


Solution

  • You might be looking for something like this?

    demo

    (I changed the colour palette as the lighter blue shades aren't really readable as text labels; feel free to change based on your needs.)

    Code with comments inline to explain the modifications made to your original version:

    ggplot(
      data_df %>% filter(group != "other"), 
      aes(year, revenue, group = type)
    ) + 
      # removed the first geom layer as it's not really contributing anything
      geom_col(                                           # geom_col() = geom_bar(stat = "identity")
        aes(fill = group)) +
      scale_fill_brewer(aesthetics = c("colour", "fill"), # add this so the fill palette appiles
                                                          # to both colour & aesthetic mappings
                        palette = "Dark2") +              # I changed to a darker palette for readability
      ggrepel::geom_text_repel(
        aes(color = group, label = label_type ),
        position = position_stack(vjust = 0.5),           # specify stacked position to follow bar layer's default position
        size = 8,
        direction = "y",
        xlim = c(2014.8, NA),
        hjust = 0,
        segment.size = .7,
        segment.alpha = .5,
        segment.linetype = "dotted",
        box.padding = .4,
        segment.curvature = -0.1,
        segment.ncp = 3,
        segment.angle = 20
      ) +
      coord_cartesian(
        clip = "off",
        ylim = c(0,25000)
      ) +
      theme_stacked_bar()