R: Apply a function recursively to a tree

tree_apply {ggraph} | R Documentation

## Apply a function recursively to a tree

### Description

This function allows for easy recursive function calling of tree-like structures. The recursion can happen either downwards, calling the children after the parent, or upwards, calling the parent after the children. At each recursion there is access to the node(s) that was/were called before and thus have already been through the function.

### Usage

    tree_apply(tree, FUN, ...)

    ## Default S3 method:
    tree_apply(tree, FUN, ...)

    ## S3 method for class 'igraph'
    tree_apply(tree, FUN, direction = "down", mode = "out",
      ...)

    ## S3 method for class 'dendrogram'
    tree_apply(tree, FUN, direction = "down", ...)

### Arguments

`tree` | A tree-like object. Currently support for igraph objects
`FUN` | The function to apply to each node. The function must return a modified version of the graph if `class(tree) == 'igraph'` or a modified version of the node if `class(tree) == 'dendrogram'`
`...` | Additional parameters to `FUN`
`direction` | The direction of the recursion. If `direction = 'down'` The parent will get handled before the children, while the reverse is true if `direction = 'up'`
`mode` | For `class(tree) == 'igraph'` the directionality of the edges in the graph. If `mode = 'out'` then parents points towards their children, while the reverse is true for `mode = 'in'`

### Details

The function is called with a set of predifined parameters along with user defined ones. If `direction = 'down'` The parameters supplied automatically to the function are: `node`, `parent`, `depth` and `tree`, while if `direction = 'up'` the parameters are: `node`, `children`, `depth` and `tree`. The nature of `node`, `parent` and `children` depends on the class of `tree`. If `class(tree) == 'igraph'` they will be indices of the relevant vertices in the graph. If `class(tree) == 'dendrogram'` they will be the actual dendrogram objects.

### Value

A modified version of `tree` (if anything is modified in `FUN`)

### Examples

    # We'll start with igraph
    require(igraph)
    gr <- graph_from_data_frame(flare$edges, vertices = flare$vertices)

    # Set depth and a class based on the name of the 2nd level node name
    gr <- tree_apply(gr, function(node, parent, depth, tree) {
      tree <- set_vertex_attr(tree, 'depth', node, depth)
      if (depth == 1) {
        tree <- set_vertex_attr(tree, 'Class', node, V(tree)$shortName[node])
      } else if (depth > 1) {
        tree <- set_vertex_attr(tree, 'Class', node, V(tree)$Class[parent])
      }
      tree
    })

    # For dendrograms it's slightly different
    irisDen <- as.dendrogram(hclust(dist(iris[1:4], method='euclidean'),
                             method='ward.D2'))
    # Add the species information to the leafs
    irisDen <- dendrapply(irisDen, function(d) {
      if(is.leaf(d))
        attr(d, 'nodePar') <- list(species=iris[as.integer(attr(d, 'label')),5])
      d
    })

    # Set class of node to the class of it's children they are of equal class
    irisDen <- tree_apply(irisDen, function(node, children, ...) {
      if (is.leaf(node)) {
        attr(node, 'Class') <- attr(node, 'nodePar')$species
      } else {
        classes <- unique(sapply(children, attr, which = 'Class'))
        if (length(classes) == 1 && !anyNA(classes)) {
          attr(node, 'Class') <- classes
        } else {
          attr(node, 'Class') <- NA
        }
      }
      node
    }, direction = 'up')

[Package ggraph version 1.0.0 Index]