rggplot2legendgeom

Split legend by axis in geom_parallel_set plot


I would like to split the legend of the plot below by axis. One for the "Class","Sex", "Age", and "Survivded".

Example parallel sets

library(ggforce)
?geom_parallel_sets

data <- reshape2::melt(Titanic)
data <- gather_set_data(data, 1:4)
ggplot(data, aes(x, id = id, split = y, value = value)) +
  geom_parallel_sets(aes(fill = Class), alpha = 0.3, axis.width = 0.1) +
  geom_parallel_sets_axes(aes(fill=y), axis.width = 0.1) +
  geom_parallel_sets_labels(colour = 'white') +
  scale_x_discrete(limits = c("Class", "Sex", "Age", "Survived"), expand = c(0, 0)) +
  theme(
    panel.background = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.y = element_blank(),
    axis.title.x = element_blank()
  )

I have researched the documentation examples without success.


Solution

  • Based on your comment, to omit certain legend items without affecting the plot, you could use scale_fill_manual with guide = guide_legend(...) to suppress the relevant legend keys and labels. Note that because your variables are factors, as.character() is needed to return the text values.

    First, create hex colour and label vectors:

    library(ggforce)
    
    # Return vector of legend values
    unique_vars <- unique(unlist(data[,c("Class", "Sex", "Age", "Survived")]))
    
    # Create vector of hex colour values for all legend items with
    # colours to match default ggplot2 colours (as in your example plot)
    legend_col <- scales::hue_pal()(length(unique_vars))
    

    Omit "No" and "Yes":

    ggplot(data, aes(x, id = id, split = y, value = value)) +
      geom_parallel_sets(aes(fill = Class), alpha = 0.3, axis.width = 0.1) +
      geom_parallel_sets_axes(aes(fill = y), axis.width = 0.1) +
      geom_parallel_sets_labels(colour = 'white') +
      scale_x_discrete(limits = c("Class", "Sex", "Age", "Survived"), expand = c(0, 0)) +
      scale_fill_manual(
        name = "Variables",
        values = legend_col,
        labels = c(as.character(unique_vars[1:8]), "", ""),
        guide = guide_legend(override.aes = list(fill = c(legend_col[1:8], NA, NA)))
      ) +
      theme(
        legend.key = element_rect(fill = NA, colour = NA),
        panel.background = element_blank(),
        axis.ticks.y = element_blank(),
        axis.text.y = element_blank(),
        axis.title.x = element_blank()
      )
    

    1

    Omit "Child" and "Adult":

    ggplot(data, aes(x, id = id, split = y, value = value)) +
      geom_parallel_sets(aes(fill = Class), alpha = 0.3, axis.width = 0.1) +
      geom_parallel_sets_axes(aes(fill = y), axis.width = 0.1) +
      geom_parallel_sets_labels(colour = 'white') +
      scale_x_discrete(limits = c("Class", "Sex", "Age", "Survived"), expand = c(0, 0)) +
      scale_fill_manual(
        name = "Variables",
        values = legend_col,
        labels = c(as.character(unique_vars[c(1:6, 9:10)]), "", ""),
        guide = guide_legend(override.aes = list(fill = c(legend_col[c(1:6, 9:10)], NA, NA)))
      ) +
      theme(
        legend.key = element_rect(fill = NA, colour = NA),
        panel.background = element_blank(),
        axis.ticks.y = element_blank(),
        axis.text.y = element_blank(),
        axis.title.x = element_blank()
      )
    

    2