2

Probably very simple,

I have a dendrogram:

set.seed(1)
my_mat <- matrix(rnorm(100),nrow=10,ncol=10)
my_dend <- as.dendrogram(hclust(dist(my_mat)))

and I want to use dendrapply to extract the height attribute from every node in my_dend, since it traverses the dendrogram in pre-order.

Trying dendrapply's example on my_dend:

dendrapply(my_dend, function(n) utils::str(attributes(n)))

It doesn't return a value but prints the information I need in pre-order. I thought that just getting the height attribute returned is as simple as:

dendrapply(my_dend, function(n) attr(n,"height"))

but obviously I'm wrong.

Any idea?

Tal Galili
  • 24,605
  • 44
  • 129
  • 187
user1701545
  • 5,706
  • 14
  • 49
  • 80

3 Answers3

2

Is this what you want?

sapply(hclust(dist(my_mat)), '[')$height
#[1] 2.195193 2.661372 2.837259 2.890944 3.745600 4.098533 4.177088 5.514541 6.496675
#and order
sapply(hclust(dist(my_mat)), '[')$order
# [1]  4  1 10  8  9  2  5  7  3  6

There's also dendextend_get_branches_heights in library dendextend

dendextend_get_branches_heights(my_dend)
#[1] 2.195193 2.661372 2.837259 2.890944 3.745600 4.098533 4.177088 5.514541 6.496675
d.b
  • 32,245
  • 6
  • 36
  • 77
  • I don't think so. dendrapply prints Heights in pre-order, which is what I'm interested in – user1701545 Feb 15 '17 at 02:17
  • I updated my question to specify that I'm interested in pre-order, which is how dendrapply seems to be traversing, unlike looping over the hclust object or using dendextend – user1701545 Feb 15 '17 at 02:30
1

To get the height of all nodes in your dendrogram, you can use the function get_nodes_attr from the dendextend package.

library(dendextend)
get_nodes_attr(my_dend, "height")

 [1] 6.496675 0.000000 5.514541 3.745600 2.195193 0.000000 0.000000 2.890944
 [9] 0.000000 0.000000 4.177088 2.837259 0.000000 0.000000 4.098533 0.000000
[17] 2.661372 0.000000 0.000000
G5W
  • 36,531
  • 10
  • 47
  • 80
0

This is by far from elegant but works:

save the output of

dendrapply(my_dend, function(n) utils::str(attributes(n)))

to a file, and edit that file:

  out.fn <- "dendrogram.output"
  capture.output(dendrapply(my_dend, function(n) utils::str(attributes(n))),file=out.fn)
  system(paste0("sed -i '/List of/d' ",out.fn))
  system(paste0("sed -i '/\\[\\[/d' ",out.fn))
  system(paste0("sed -i '/NULL/d' ",out.fn))
  system(paste0("sed -i '/^$/d' ",out.fn))
  system(paste0("sed -i '/class/d' ",out.fn))
  system(paste0("sed -i '/midpoint/d' ",out.fn))
  system(paste0("sed -i '/leaf/d' ",out.fn))
  system(paste0("sed -i '/label/d' ",out.fn))
  system(paste0("sed -i '/members/d' ",out.fn))
  system(paste0("sed -i 's/ \\$ //g' ",out.fn))
  system(paste0("perl -i -pe 's/height\\s+:\\s+num\\s+//g' ",out.fn))

  my_dend.df <- dplyr::filter(read.table(out.fn,header=F,sep=",",stringsAsFactors=F,col.names="depth"),depth != 0)

> my_dend.df
  depth
1  6.50
2  5.51
3  3.75
4  2.20
5  2.89
6  4.18
7  2.84
8  4.10
9  2.66
user1701545
  • 5,706
  • 14
  • 49
  • 80