Stochastic character mapping (SIMMAP)

What it does. Stochastic character mapping (Huelsenbeck et al. 2003; Nielsen 2002) generates a random sample of histories of a discrete trait on a phylogeny conditional on the tip states and a model of evolution (typically Mk). Each mapped history assigns a particular state to every point along every branch — not just to nodes. Running make.simmap in phytools produces many such histories (typically 100–1000); the ensemble captures phylogenetic uncertainty about when and how often transitions occurred. The describe.simmap function summarizes across maps: expected number of changes, proportion of time spent in each state, and state-dependent ancestral probabilities at nodes.

When to use it.

When NOT to use it.

Worked example

library(phytools)

# tree: ape phylo object (ultrametric)
# x: named character vector of discrete states (e.g., "XY", "XO")
#    names must match tree$tip.label exactly

# 1. Fit an Mk model to estimate Q before mapping
#    Using fitMk from phytools (wraps ace internally)
fit <- fitMk(tree, x, model = "ARD")
fit$rates   # estimated q01 and q10

# 2. Generate 1000 stochastic character maps using the estimated Q
#    model = "ARD" uses the empirical Bayes approach (Q estimated from data)
maps <- make.simmap(tree, x, model = "ARD", nsim = 1000,
                    message = FALSE)

# 3. Summarise the ensemble
summary_obj <- describe.simmap(maps, plot = FALSE)

# Mean number of changes per state transition
summary_obj$Ntransitions

# Proportion of time spent in each state per branch
# (rows = branches, columns = states)
head(summary_obj$times)

# Marginal node state probabilities (average across maps)
head(summary_obj$ace)

# 4. Plot the first 4 maps to see the range of histories
par(mfrow = c(2, 2))
for (i in 1:4) {
  plot(maps[[i]], fsize = 0.3, lwd = 2)
}

# 5. Count total XO -> XY transitions across all maps
trans <- sapply(maps, function(m) {
  countSimmap(m)$Tr["XO,XY"]
})
mean(trans)
quantile(trans, c(0.025, 0.975))

Gotchas we’ve hit

Key papers that use this method in the lab

Question copied. Paste it into the NotebookLM tab.