Expected values for random trees

Context for tree distances can be provided by comparison with the distance expected for a pair of random trees.

The figure below shows how the median normalized tree distance varies with the number of leaves in the trees being compared. 1 000 random pairs of n-leaf trees were generated for $4 \leq n \leq 200$r ''#4 ≤ _n_ ≤ 200, and the distances between them calculated. Shaded envelopes denote the interdecile and interquartile ranges. The raw data are available in the data object randomTreeDistances.

```{R calculations, echo=FALSE, message=FALSE, cache=TRUE} library('TreeDistData') data('tdMethods', package = 'TreeDistData') data('tdAbbrevs', package = 'TreeDistData') methods <- tdMethods abbrevs <- tdAbbrevs

totalInfoContent <- 3L methodLCH <- colorspace::coords(as(colorspace::hex2RGB(TreeDistCol(methods)), 'polarLUV'))

data('randomTreeDistances', package = 'TreeDistData') pathMax <- randomTreeDistances['path', 'max', ] msMax <- randomTreeDistances['ms', 'max', ] kcMax <- randomTreeDistances['kc', 'max', ]

nTip <- as.integer(dimnames(randomTreeDistances)[[3]])

pathNorm <- lm(log(pathMax) ~ log(nTip)) msNorm <- lm(log(msMax) ~ log(nTip)) kcNorm <- vapply(nTip, TreeDist::KCDiameter, 1) nniNorm <- TreeDist::NNIDiameter(nTip)

normalizeAgainst <- rbind( path = exp(predict(pathNorm)), ms = exp(predict(msNorm)), nni_u = nniNorm[, 'max'], nni_U = nniNorm[, 'max'], nni_l = nniNorm[, 'min'], nni_L = nniNorm[, 'min'], spr = nTip / 2L, tbr_u = nTip, tbr_l = nTip, rf = (nTip - 3L) * 2L, mast = nTip, masti = TreeTools::LnUnrooted(nTip) / log(2), kc = kcNorm, es = kcNorm )

AddLine <- function (method, normalize = FALSE) { dat <- randomTreeDistances[method, , ] dat <- dat[, !is.na(dat[1, ])] nLeaves <- colnames(dat) if (normalize) dat <- dat / rep(normalizeAgainst[method, nLeaves], each = dim(dat)[1L]) Invert <- function (dat) { dat['mean', ] <- 1 - dat['mean', ] dat[c("min", "1%", "5%", "10%", "25%", "50%", "75%", "90%", "95%", "99%", "max"), ] <- 1 - dat[c("max", "99%", "95%", "90%", "75%", "50%", "25%", "10%", "5%", "1%", "min"), ] dat } if (method %in% c('mast', 'masti')) dat <- Invert(dat)

col <- TreeDistCol(method, '')

lines(nLeaves, dat['50%', ], pch = 1, col = col) polygon(c(nLeaves, rev(nLeaves)), c(dat['10%', ], rev(dat['90%', ])), border = NA, col = paste0(col, '33'),) polygon(c(nLeaves, rev(nLeaves)), c(dat['25%', ], rev(dat['75%', ])), border = NA, col = paste0(col, '33'),) #lines(nLeaves, dat['25%', ], lty = 2, col = col) #lines(nLeaves, dat['75%', ], lty = 2, col = col) #pointsAt <- 1:10 * 20L }

```{R tree-distance-averages, echo=FALSE, message=FALSE, cache=TRUE, fig.asp=2.8, fig.width=6, fig.align='center'}
origPar <- par(mfrow = c(4, 1), cex = 0.7, oma = rep(0, 4), 
               mar = c(5, 5, 0.01, 0.01))
PlotMethods <- function (methods, yMin = 0.4,
                         lp = c('bottomright', 'bottomleft')) {
  plot(as.integer(dimnames(randomTreeDistances)[[3]]),
       randomTreeDistances['pid', 'mean', ],
       ylim = c(yMin, 1), type = 'n',
       xlab = "Number of leaves", ylab = "Normalized tree distance")
  for (method in methods) AddLine(method, 
                                  method %in% c('ms', rownames(normalizeAgainst)))


  legend(lp[1], bty = 'n',
         lty = 1, legend = abbrevs[methods], col = TreeDistCol(methods, 44),
         text.col = '#FFFFFFFF', pch = 15, pt.cex = 1.8
  )

  legend(lp[1], bty = 'n', lty = 1, 
         legend = abbrevs[methods], col = TreeDistCol(methods))

  legend(lp[2], bty = 'n', inset = c(0.09, 0),
         lty = 1, lwd = c(1, 4, 6), col = c(1, "#00000066", "#00000033"),
         legend = c('Median', 'Interquartile range', 'Interdecile range'))
}
PlotMethods(c('rf', 'pid', 'cid', 'nye', 'msid'))
PlotMethods(c('jnc4', 'jco4', 'jnc2', 'jco2', 'nye'), yMin = 0.7)
PlotMethods(c('ms', 'masti', 'mast', 'path', 'qd'), yMin = 0.42)
PlotMethods(c('kc', 'es', 'tbr_u', 'spr', 'nni_u', 'nni_l', 'tbr_l'), yMin = 0.13)
par(origPar)

Information-based metrics are normalized against the total information content of each pair of trees. The (Jaccard–)Robinson–Foulds, Nye et al., maximum agreement subtree and Quartet metrics are normalized based on the maximum possible value. The SPR distance is normalized against n / 2; this value lies between the definitive bounds of the maximum diameter of the SPR distance [@Allen2001], and was not exceeded by any of the random tree pairs. The TBR distance is normalized against n. The Kendall–Colijn distance is normalized against the distance between a pair of oppositely-rooted pectinate trees. The path, Matching Split Distance and NNI metrics do not have a readily calculated maximum value and are thus crudely 'normalized' against an approximate maximum, estimated by fitting a polynomial to the the maximum observed distance for each number of leaves. Candidate polynomial functions were evaluated based on the Akaike and Bayesian information criteria.

Note that the path and Matching Splits distances exhibit a prominently larger variability than other metrics, suggesting that they are less consistent in the score that they assign to a random pair of trees. In combination with the difficulty in calculating the range of these metrics, this makes their absolute value difficult to interpret.

Ranges

Average range of distance between random trees with 20–200 leaves, expressed as percentages of the median.

{R normalized-range, echo=FALSE, message=FALSE, cache=TRUE, output='asis'} IQRNorm <- function (methodDistances) { iqr <- abs(methodDistances['75%', ] - methodDistances['25%', ]) iqr / methodDistances['50%', ] } iq <- colMeans(apply(randomTreeDistances, 1, IQRNorm)[as.character(20:200), ], na.rm = TRUE) names(iq) <- tdMdAbbrevs[names(iq)] .TDDTable(DT::datatable, cbind("Range (%)" = round(iq[order(iq, decreasing = FALSE)] * 100, 2)))

References



ms609/TreeDistData documentation built on May 21, 2021, 6:53 a.m.