dendrapply {stats} | R Documentation |
Apply function FUN
to each node of a dendrogram
recursively. When y <- dendrapply(x, fn)
, then y
is a
dendrogram of the same graph structure as x
and for each node,
y.node[j] <- FUN( x.node[j], ...)
(where y.node[j]
is an
(invalid!) notation for the j-th node of y).
dendrapply(X, FUN, ..., how = c("pre.order", "post.order"))
X |
an object of class |
FUN |
an R function to be applied to each dendrogram node,
typically working on its |
... |
potential further arguments passed to |
how |
one of |
"pre.order"
preserves the functionality of the previous
dendrapply
. For each node n
, FUN
is applied
first to n
, then to n[[1]]
(and any children it may have),
then n[[2]]
and its children, etc. Notably, each node is evaluted
prior to any of its children.
"post.order"
allows for calculations that depend on the
children of a given node. For each node n
, FUN
is
applied first to all children of n
, then is applied to
n
itself. Notably, each node is evaluated after all of
its children.
Usually a dendrogram of the same (graph) structure as X
.
For that, the function must be conceptually of the form
FUN <- function(X) { attributes(X) <- .....; X }
,
i.e., returning the node with some attributes added or changed.
If the function provided does not return the node, the result is
a nested list of the same structure as X
, or as close as can
be achieved with the return values. If the function should only be
applied to the leaves of X
, consider using
rapply
instead.
dendrapply
identifies leaf nodes as nodes
such that attr(node, 'leaf') == TRUE
, and internal nodes
as nodes such that attr(node, 'leaf') %in% c(NULL, FALSE)
.
If you modify or remove this attribute, dendrapply
may perform
unexpectedly.
The prior implementation of dendrapply
was recursive and
inefficient for dendrograms with many non-leaves. This version is
no longer recursive, and thus should no longer cause issues stemming
from insufficient C stack size (as mentioned in the 'Warning' in
dendrogram
).
Aidan Lakshman ahl27@pitt.edu.
Original function and documentation by Martin Maechler.
as.dendrogram
, lapply
for applying a function to each component of a list.
rapply
is particularly useful for applying a
function to the leaves of a dendrogram, and almost always be used
when the function does not need to be applied to interior nodes due
to significantly better performance.
require(graphics)
## a smallish simple dendrogram
dhc <- as.dendrogram(hc <- hclust(dist(USArrests), "ave"))
(dhc21 <- dhc[[2]][[1]])
## too simple:
dendrapply(dhc21, function(n) utils::str(attributes(n)))
## toy example to set colored leaf labels :
local({
colLab <<- function(n) {
if(is.leaf(n)) {
a <- attributes(n)
i <<- i+1
attr(n, "nodePar") <-
c(a$nodePar, list(lab.col = mycols[i], lab.font = i%%3))
}
n
}
mycols <- grDevices::rainbow(attr(dhc21,"members"))
i <- 0
})
dL <- dendrapply(dhc21, colLab)
op <- par(mfrow = 2:1)
plot(dhc21)
plot(dL) ## --> colored labels!
par(op)
## Illustrating difference between pre.order and post.order
dend <- as.dendrogram(hclust(dist(seq_len(4L))))
f <- function(x){
if(!is.null(attr(x, 'leaf'))){
v <- as.character(attr(x, 'label'))
} else {
v <- paste0(attr(x[[1]], 'newattr'), attr(x[[2]], 'newattr'))
}
attr(x, 'newattr') <- v
x
}
# trying with default, note character(0) entries
preorder_try <- dendrapply(dend, f)
dendrapply(preorder_try, \(x){ print(attr(x, 'newattr')); x })
## trying with postorder, note that children nodes will already
## have been populated, so no character(0) entries
postorder_try <- dendrapply(dend, f, how='post.order')
dendrapply(postorder_try, \(x){ print(attr(x, 'newattr')); x })