rggplot2labelsankey-diagram

Adjust labels on individual nodes in Sankey diagram using ggsankey


I am making a Sankey diagram using ggsankey and am having a difficult time getting my labels to be visible when they overlap on the nodes. I have three nodes and want to move the labels on the left hand side so it doesn't overlap the node, but rather sits to left of the node. I want the node in the middle to stay centered on the node, and i want to move the labels on the right hand side so the sit to the right of the right hand node.

I can get all the labels to move position using geom_sankey_label and hjust but I can't figure out how to move labels on each node separately. I can't even really tell if it is possible to do what I want.

My code is very similar to this-

df <- mtcars %>%
  make_long(cyl, vs, am, gear, carb)

ggplot(df, aes(x = x, next_x = next_x, node = node, next_node = next_node, fill = factor(node), label = node)) +
  geom_sankey(flow.alpha = .6,
              node.color = "gray30",
              space = 20) +
  geom_sankey_label(size = 3, 
                    color = "white", 
                    fill = "gray40",
                    hjust = 0,
                    position = position_nudge(x = 0.1),
                    space = 20) +
  scale_fill_viridis_d() +
  theme_sankey(base_size = 18) +
  labs(x = NULL) +
  theme(legend.position = "none",
        plot.title = element_text(hjust = .5)) +
  ggtitle("Car features")

sankey plot with labels moved off nodes

and i want it to look like this rough sketch: enter image description here


Solution

  • One option to achieve your desired result would be to conditionally nudge your labels and set the alignment of the labels using e.g. dplyr::case_when inside aes(). To nudge the position of the labels I make use of ggplot2::stage():

    library(ggplot2)
    library(ggsankey)
    
    df <- mtcars |>
      make_long(cyl, vs, am, gear, carb)
    
    ggplot(df, aes(
      x = x, next_x = next_x,
      node = node, next_node = next_node,
      fill = factor(node), label = node
    )) +
      geom_sankey(
        flow.alpha = .6,
        node.color = "gray30",
        space = 20
      ) +
      geom_sankey_label(
        aes(
          # Shift labels conditional on position
          x = stage(x,
            after_stat = x + .1 *
              dplyr::case_when(
                x == 1 ~ -1,
                x == 5 ~ 1,
                .default = 0
              )
          ),
          # Align labels conditional on position
          hjust = dplyr::case_when(
            x == "cyl" ~ 1,
            x == "carb" ~ 0,
            .default = .5
          )
        ),
        size = 3,
        color = "white",
        fill = "gray40",
        space = 20
      ) +
      scale_fill_viridis_d() +
      theme_sankey(base_size = 18) +
      theme(
        legend.position = "none",
        plot.title = element_text(hjust = .5)
      ) +
      labs(x = NULL, title = "Car features")