Search code examples
rhierarchical-datadata.treecollapsibletree-r

Adding a "fill" attribute to a data.tree object for use in collapsibleTree in R


We've been using dataframes with collapsibleTree() to make interactive, nice looking dendograms of hierarchical systems. The issue we have though is that it's difficult to get the customization we want when using a dataframe and it seems from the collapsibleTree documentation that using data.tree structure provides for more flexibility. For example, if we want to color specific nodes with a dataframe, we need to do something like this:

library(dplyr)
library(data.tree)
library(collapsibleTree)

colors <- rep('gray', 15)
colors[1] <- 'red' # root
colors[3] <- 'red' # child we want to emphasize
colors[15] <- 'red' # grand child we want to emphasize

original_data_frame %>% 
  collapsibleTree(
    hierarchy = c("level_2",
                  "level_3",
                  "level_4",
                  "level_5",
                  "level_6",
                  "level_7"
    ),
    root = "level_1",
    fill = colors
  )

This isn't really a good solution, especially when the resulting tree has hundreds or more nodes or higher levels of hierarchy.

I saw that in data.tree, I should be able add arbitrary attributes but this doesn't seem to be working, at least it's not having the desired affect I want it to have:

original_as_tree <- original_data_frame %>% 
    mutate(pathString =
           paste(
             level_1,
             level_2,
             level_3,
             level_4,
             level_5,
             level_6,
             level_7,
             sep = "/"),
           pathString = str_remove_all(pathString, "/NA")) %>% 
  as.Node()

original_as_tree$color <- "gray"
original_as_tree$Boat$color <- "red"

collapsibleTree(original_as_tree,
                fill = original_as_tree$color)

This just colors each node "gray" (or red if I did original_as_tree$Boat$color). Ideally, I'd be able to assign colors programmatically with some sort of case_when or ifelse call.

Here's the dput of my example data:

structure(list(level_1 = c("Sea System", "Sea System", "Sea System", 
"Sea System", "Sea System", "Sea System"), level_2 = c("System Engineering", 
"Boat", "Boat", "Boat", "Boat", "Boat"), level_3 = c("Core Systems Engineering", 
"Auxiliary Systems", "Total Ship Integration/Engineering", "Electric Plant", 
"Hull Structure", "Hull Structure"), level_4 = c(NA_character_, 
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_
), level_5 = c(NA_character_, NA_character_, NA_character_, NA_character_, 
NA_character_, NA_character_), level_6 = c(NA_character_, NA_character_, 
NA_character_, NA_character_, NA_character_, NA_character_), 
    level_7 = c("GREENLAND ENTERPRISES, INC.", "3M PURIFICATION INC.", 
    "5TH AXIS, LLC", "901 D, LLC", "A. M. CASTLE & CO.", "A.M. CASTLE & CO."
    )), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"

Solution

  • Seems I'm little late to the party on this one! I just used the acme data included in data.tree as an example. I'm using data.table out of preference but the same idea applies with dplyr - one way to get what you want would be to create a column specifying colors before converting to a data.tree.

    library(data.tree)
    library(data.table)
    library(collapsibleTree)
    
    # example df
    data(acme)
    acme_df = ToDataFrameTree(acme, "pathString", "cost") 
    acme_dt = as.data.table(acme_df)
    
    # create a color column
    acme_dt[, color := ifelse(is.na(cost), "red", "blue")]
    
    # convert dt to Node
    acme_tree = as.Node(acme_dt, "cost", "color")
    
    # collapsible tree
    collapsibleTree(acme_tree, fill = "color")
    

    Hopefully this is helps!