r-causal / ggdag

:arrow_lower_left: :arrow_lower_right: An R package for working with causal directed acyclic graphs (DAGs)
https://r-causal.github.io/ggdag/
Other
433 stars 28 forks source link

Multiple nodes the same colour? #138

Closed boshek closed 8 months ago

boshek commented 8 months ago

👋 thanks for the great package. Super helpful docs.

I have, what is probably a complete noob question purely about having attributes in a tidy dag object. I've created a reprex below. I am wondering how to colour nodes according to a grouping variable that is attributed to multiple nodes. In my reprex I have lookup_table which indicates that both 0 and 1 should coloured with "X". However when I join this I think I am only labelling the edges though the colouring (or label) also does show up in the points. Is there a way with {ggdag} to have 0 and 1 both be the same colour?

library(ggdag)
library(dplyr)
library(ggplot2)

lookup_tbl <- data.frame(
  name = c(0, 1, 2, 3),
  label = c("X", "X", "Y", "Z")
)

dag_df <- data.frame(
  name = c(1, 2, 3),
  to = c(0, 1, 1)
) |>
  left_join(lookup_tbl, by = c("name" = "name")) %>%
  as_tidy_dagitty(layout = "sugiyama")

dag_df |>
  ggplot(aes(x = x, y = y, xend = xend, yend = yend, color = label, label = label)) +
  geom_dag_point() +
  geom_dag_edges() +
  geom_dag_text(col = "white") +
  theme_dag()

malcolmbarrett commented 8 months ago

Hi there,

This is mostly a simple join problem! You're joining the labels to name in your initial data frame but 0 isn't in that column, so it ends up NA. By moving the join to after the creation of the tidy_dagitty object, you can correctly join.

I also moved two of the aesthetics: color to the point geom so you don't have to override the color of the text and label to the text geom so you don't get a label on the edges too. (The fact that you can add labels to the edges is super handy but doesn't seem like what you want here).

library(ggdag)
library(dplyr)
library(ggplot2)

lookup_tbl <- data.frame(
  name = as.character(c(0, 1, 2, 3)),
  label = c("X", "X", "Y", "Z")
)

dag_df <- data.frame(
  name = c(1, 2, 3),
  to = c(0, 1, 1)
) %>%
  as_tidy_dagitty(layout = "sugiyama") |>
  left_join(lookup_tbl, by = c("name" = "name"))

dag_df |>
  ggplot(aes(x = x, y = y, xend = xend, yend = yend)) +
  geom_dag_point(aes(color = label)) +
  geom_dag_edges() +
  geom_dag_text(aes(label = label)) +
  theme_dag()

Created on 2024-01-30 with reprex v2.1.0

As a side note, the data.frame() |> as_tidy_dagitty() API is fairly new, so you might kind some kinks. I encourage you to file any issues you might find

boshek commented 8 months ago

🤦 . Right there in front of me. Thank you!

malcolmbarrett commented 8 months ago

As a side note, the data.frame() |> as_tidy_dagitty() API is fairly new, so you might kind some kinks. I encourage you to file any issues you might find

FYI, I found a substantial bug in how the underlying dagitty objects are created with this API, meaning the visualizations work but the algorithms are incorrect. It's now fixed on the dev version