0

I created a ggplot graph using ggsegment for certain subcategories and their cost.

df <- data.frame(category = c("A","A","A","A","A","A","B","B","B","B","B","B","B"),
                 subcat = c("S1","S2","S3","S4","S5","S6","S7","S8","S9","S10","S11","S12","S13"),
                 value = c(100,200,300,400,500,600,700,800,900,1000,1100,1200,1300))


df2 <- df %>%
  arrange(desc(value)) %>%
  mutate(subcat=factor(subcat, levels = subcat)) %>%
  ggplot(aes(x=subcat, y=value)) +
  geom_segment(aes(xend=subcat, yend=0)) +
  geom_point(size=4, color="steelblue") +
  geom_text(data=df, aes(x=subcat, y=value, label = dollar(value, accuracy = 1)), position = position_nudge(x = -0.3), hjust = "inward") +
  theme_classic() +
  coord_flip() +
  scale_y_continuous(labels = scales::dollar_format()) +
  ylab("Cost Value") +
  xlab("subcategory")

df2

This code results in a graph that is shown below:

enter image description here

My main issue is I want the category variable on the left of the subcategory variables. It should look like this:

enter image description here

How do I add the category variables in the y-axis, such that it looks nested?

benson23
  • 16,369
  • 9
  • 19
  • 38
knick
  • 37
  • 4
  • You could do the "facet" trick. See e.g. [How to create a ggplot in R that has multilevel labels on the y axis and only one x axis](https://stackoverflow.com/questions/71178723/how-to-create-a-ggplot-in-r-that-has-multilevel-labels-on-the-y-axis-and-only-on) – stefan Feb 18 '22 at 23:30

1 Answers1

1

As mentioned in my comment and adapting this post by @AllanCameron to your case one option to achieve your desired result would be the "facet trick", which uses faceting to get the nesting and some styling to remove the facet look:

  1. Facet by category and free the scales and the space so that the distance between categories is the same.
  2. Remove the spacing between panels and place the strip text outside of the axis text.
  3. Additionally, set the expansion of the discrete x scale to .5 to ensure that the distance between categories is the same at the facet boundaries as inside the facets.
library(dplyr)
library(ggplot2)
library(scales)

df1 <- df %>%
  arrange(desc(value)) %>%
  mutate(subcat=factor(subcat, levels = subcat))

ggplot(df1, aes(x=subcat, y=value)) +
  geom_segment(aes(xend=subcat, yend=0)) +
  geom_point(size=4, color="steelblue") +
  geom_text(data=df, aes(x=subcat, y=value, label = dollar(value, accuracy = 1)), position = position_nudge(x = -0.3), hjust = "inward") +
  theme_classic() +
  coord_flip() +
  scale_y_continuous(labels = scales::dollar_format()) +
  scale_x_discrete(expand = c(0, .5)) +
  facet_grid(category~., scales = "free_y", switch = "y", space = "free_y") +
  ylab("Cost Value") +
  xlab("subcategory") +
  theme(panel.spacing.y = unit(0, "pt"), strip.placement = "outside")

stefan
  • 90,330
  • 6
  • 25
  • 51