Adjust labels on individual nodes in Sankey diagram using ggsankey

24 Views Asked by At

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

1

There are 1 best solutions below

1
stefan On BEST ANSWER

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")