Search code examples
rggplot2facet-wrap

Adding white spaces along x axis in ggplot


I'm trying to figure out the best way to add a little space between types of variables along the x axis (which looks like the the y axis here since I'm flipping coordinates).

As you can see, I'm faceting by the "type" variable, but then I have three different categories of "group" variable: race, sex, and region. As of now I've got them in different colors, which helps, but ideally I'd be able to add a little white space between them. Any good ideas?

Code:

order <- c("white", "black", "hispanic", "female", "male", "north", "south")

ggplot(d, aes(x = group, y = percent, fill = group)) +
  geom_bar(stat = "identity") + 
  facet_wrap(~type) +
  coord_flip() +
  scale_x_discrete(limits = order) +
  scale_fill_manual(values = c("white" = "skyblue",
                               "black" = "skyblue",
                               "hispanic" = "skyblue",
                               "male" = "indianred1",
                               "female" = "indianred1",
                               "north" = "goldenrod2",
                               "south" = "goldenrod2")) +
  theme_minimal() +
  theme(legend.position = "none")

Data example:

structure(list(group = c("white", "white", "white", "black", 
"black", "black", "hispanic", "hispanic", "hispanic", "male", 
"male", "male", "female", "female", "female", "south", "south", 
"south", "north", "north", "north"), percent = c(0.34, 0.23, 
0.2, 0.04, 0.5, 0.3, 0.14, 0.52, 0.2, 0.13, 0.43, 0.34, 0.43, 
0.3, 0.3, 0.14, 0.09, 0.42, 0.22, 0.1, 0.05), type = c("typeA", 
"typeB", "typeC", "typeA", "typeB", "typeC", "typeA", "typeB", 
"typeC", "typeA", "typeB", "typeC", "typeA", "typeB", "typeC", 
"typeA", "typeB", "typeC", "typeA", "typeB", "typeC")), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -21L), spec = structure(list(
    cols = list(group = structure(list(), class = c("collector_character", 
    "collector")), percent = structure(list(), class = c("collector_double", 
    "collector")), type = structure(list(), class = c("collector_character", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1L), class = "col_spec"))

enter image description here


Solution

  • One option to achieve your desired result would be4 to switch to facet_grid. To this end add a column containing the categories by which you want to to group your items or groups which could then be used to facet in the y direction. Additional benefit of doing so would be that you can now color by category instead of by group.

    library(ggplot2)
    library(dplyr)
    
    d <- d |>
      mutate(
        cat = case_when(
          group %in% c("male", "female") ~ "sex",
          group %in% c("south", "north") ~ "region",
          TRUE ~ "race"
        ),
        group = factor(group, levels = order),
        cat = factor(cat, levels = c("region", "sex", "race"))
      )
    
    ggplot(d, aes(x = percent, y = group, fill = cat)) +
      geom_col(orientation = "y", width = .75) +
      facet_grid(cat ~ type, scales = "free_y", space = "free_y") +
      scale_fill_manual(values = c(
        "race" = "skyblue",
        "sex" = "indianred1",
        "region" = "goldenrod2"
      )) +
      theme_minimal() +
      theme(legend.position = "none", strip.text.y = element_blank())
    

    enter image description here