View source: R/correlate_categorical_traits.R
| correlate_categorical_traits | R Documentation |
Given one or more rooted phylogenetic trees and states for two categorical traits on the tree tips, examine the correlation between the two traits while accounting for phylogenetic relationships between tips. Regular correlation tests treating each tip as an independent sample fail to account for statistical dependencies between closely related tips, and thus misestimate statistical significances; this function avoids this fallacy by using a stochastic null model for trait evolution on phylogenies.
This function can handle missing states encoded as NA, erroneous state measurements provided that error rates are a priori known, as well as sampling biases provided that the biases are a priori known. The function can handle binary traits (e.g., presence/absence of wings) as well as multi-state traits (e.g., representing multiple levels of wing complexity). Multiple test statistics are examined, including Pearson correlation, Spearman rank correlation, normalized mutual information (Strehl & Ghosh 2002) and likelihood ratio test (Pagel 1994). The function supportsconventional homogeneous models sensu Pagel (1994) as well as heterogeneous hidden Markov models sensu Boyko & Beaulieu (2023).
correlate_categorical_traits(trees,
tip_states1,
tip_states2,
value_probs1 = NULL,
value_probs2 = NULL,
inclusion_probs1 = NULL,
inclusion_probs2 = NULL,
null_rate_model1 = "ARD",
null_rate_model2 = "ARD",
root_prior = "stationary",
dependent_trait = 0,
Ntrials = 10,
Ntrials_sim = 1,
Nthreads = -1,
Nsimulations = 1000,
max_model_runtime = NULL,
include_lrt = FALSE,
heterogeneous = FALSE,
verbose = FALSE,
verbose_prefix = "")
trees |
A single rooted tree of class "phylo", or a list of NT such trees. Typically, edge lengths will be in units of time (i.e., the trees are dated), but may also be in other units such as nucleotide substitutions per site. The edge length units will influence the precise meaning of the null models used. |
tip_states1 |
A list of NT integer vectors, specifying the state of each tip in each tree, for trait 1. Hence, Note that tip states must be encoded as integers >=1; for example, binary traits must be encoded using the values 1 and 2, not 0 and 1. This convention allows a direct correspondence between tip states and the indexing of other auxiliary inputs such as For non-ordinal traits, i.e., lacking any intrinsic ordering (e.g., plumage color), states may be encoded in any arbitrary order, as long as this is done consistently. Note that for such traits some computed correlation metrics such as Pearson and Spearman may not be meaningful. |
tip_states2 |
Similar to |
value_probs1 |
Optional list of NT numeric 3-dimensional arrays, each specifying conditional probabilities for measured states of trait 1 on each tree. This argument allows incorporating custom error probabilities, separately for each tip on each tree and depending on a tip's true state. Each For example, suppose trait 1 represents the absence (state 1) or presence (state 2) of a gene family in a bacterial strain, and a given tip |
value_probs2 |
Similar to |
inclusion_probs1 |
Optional list of NT numeric vectors, each specifying inclusion probabilities for trait 1 on a tree. This argument allows specifying the probability of any state being measured on a tip (as opposed to being While each For convenience, As an example, suppose binary trait 1 represents the ability of microbial species to perform methanogenesis (1:no, 2:yes), and suppose non-methanogens are known to be twice as likely than methanogens to be studied in sufficient detail to assess the trait. Then |
inclusion_probs2 |
Similar to |
null_rate_model1 |
Character, specifying the null Markov transition rate model to use for trait 1. Choices are "ARD" (all rates different), "ER" (all rates equal), "SYM" (equal rates in each direction), "SUEDE" and "SRD". For details see the documentation of |
null_rate_model2 |
Similar to |
root_prior |
Character, prior probability distribution of the root's states, used to calculate each model's likelihood during fitting. For options and explanations see the documentation of |
dependent_trait |
Integer, specifying which trait to consider as the dependent (influenced) trait during full model fitting. Options are 0 (both traits influence each other's transition rates), 1 (trait 2 influences the rates of trait 1, but not vise versa) and 2 (trait 1 influences the rates of trait 2, but not vise versa). Only relevant if |
Ntrials |
Strictly positive integer, number of independent fitting trials to attempt when fitting models to the input data. A larger number increases the chances of an optimal model fit (i.e., avoiding non-global maxima in the likelihood function), at the expense of increased computation. This argument is passed directly to |
Ntrials_sim |
Similar to |
Nthreads |
Integer, number of parallel threads to use whenever applicable. If negative, this defines the number of desired threads minus the number of available cores; for example -1 means use all cores except one. Only relevant for Linux/UNIX/MacOS; for Windows, computation is always performed in a single thread. |
Nsimulations |
Strictly positive integer, number of simulations to perform of the null model, for estimating statistical significances (aka. P-values). A larger |
max_model_runtime |
Optional numeric, maximum time (in seconds) to allocate for each likelihood evaluation per tree, during fitting. Use this to escape from badly parameterized models during fitting (this will likely cause the affected fitting trial to fail). This argument is passed directly to |
include_lrt |
Logical, whether to also perform a likelihood ratio test, i.e., fitting a "full"" Markov model where both traits may influence each other's transition rates, and comparing the maximized likelihood of the full model to the maximized likelihood of the null model (where each trait evolves independently). Setting this to |
heterogeneous |
Logical, whether to use hidden Markov models with rate heterogeneity sensu Boyko & Beaulieu (2023), i.e. where the transition rates between states depend on a hidden binary character that evolves independently according to a separate Markov model. If |
verbose |
Logical, whether to print out progress messages. |
verbose_prefix |
Character, optional line prefix for printed messages, for example to achieve a certain indentation. |
To compute the statistical significance (P value) of any given correlation coefficient, this function repeatedly simulates hypothetical tip states using the fitted null model, each time recomputing the corresponding "random" correlation coefficients, and then examines the distribution of those random correlation coefficients.
Under the null, each trait evolves along the phylogenetic trees according to a continuous-time Markov chain model ("Mk model"), independently of the other trait. In the homogeneous case (heterogeneous==FALSE), the transition rates between states are constant in time, and the null model consists of two decoupled Mk models (henceforth “partial” null models), one for each trait. For binary traits, for example, this implies 4 fitted rate parameters if both null_rate_model1 and null_rate_model2 as "ARD" (default). In the heterogeneous case sensu Boyko & Beaulieu (2023), transition rates are further influenced by a hidden, independently evolving binary character; for binary traits, this implies up to 10 fitted rate parameters (4+4+2).
The fitted null model is subsequently simulated multiple times to generate hypothetical trait data on the same trees and re-evaluating the various considered test statistics (e.g., Pearson correlations and LRT). If value_probs and/or inclusion_probs are given for a trait, simulated tip states are further modified and/or replaced by NA according to those probabilities.
If a likelihood ratio test is included (option include_lrt), then a "full" model is also fitted, and its maximized likelihood is compared to the maximized likelihood of the null. In the full model, both traits evolve according to a continuous-time Markov chain, and the state of one trait can impact the transition rates of the other trait depending on the option dependent_trait. Simultaneous transitions of both traits are not permitted in this model. In the homogeneous case (heterogeneous==FALSE), this full model thus has Nstates1 x Nstates2 states, corresponding to all possible combinations of the two traits. In the heterogeneous case, the full model has Nstates1 x Nstates2 x 2 states, due to the additional hidden binary character.
For any given state of trait 1 (and hidden binary character, if applicable), the transition rates of trait 2 will be consistent with the provided null_rate_model1, and vise versa. The statistical significance of the LRT is estimated by re-fitting the null and full model to each simulated dataset, and re-computing the corresponding LRT. Simulation-based LRT is thus the most computationally heavy mode in which this function may be used. The function also returns an asymptotic chi2-approximation for the P-value, which should generally not be used for small datasets nor for the heterogeneous case, and is provided mostly for quick preliminary checks and comparisons with other software. Nevertheless, if you only want the chi2 approximation and not the simulation-based significance, you can set Nsimulations=0 for efficiency.
A named list with the following elements:
success |
Logical, indicating whether the analyses was performed successfully. |
error |
Character, an error message if |
Nstates1 |
Integer, the inferred number of categorical states for trait 1. |
Nstates2 |
Integer, the inferred number of categorical states for trait 2. |
null_fit1 |
Named list, containing the raw partial null model fit results for trait 1, as returned by |
null_fit2 |
Similar to |
null_fit |
Named list, containing the raw heterogeneous null model fit results for both traits, as returned by |
full_fit |
Named list, containing the raw full model fit results, as returned by |
null_transition_matrix1 |
Numeric matrix of size Nstates1 x Nstates1, listing the estimated transition rates for trait 1, under the null model. The entry |
null_transition_matrix2 |
Similar to |
null_transition_matrix |
Numeric 6-dimensional array of size Nstates1 x Nstates2 x 2 x Nstates1 x Nstates2 x 2, listing the estimated joint transition rates between multi-states (s1,s2,h) under the null model, where s1 enumerates states of trait 1, s2 enumerates states of trait 2, and h enumerates the two states of the hidden rate-modulating character. For example, |
null_Nrates |
Integer, the total number of free/fitted rate parameters in the null model. |
full_Nrates |
Integer, the total number of free/fitted rate parameters in the full model. |
null_loglikelihood |
The maximized log-likelihood of the null model. |
full_loglikelihood |
The maximized log-likelihood of the full model. Only included if |
null_AIC |
The Akaike Information Criterion of the null model. |
full_AIC |
The Akaike Information Criterion of the full model. Only included if |
AIC_weights |
Numeric vector of length 2, listing the AIC weights for the null and full model, respectively (Burnham & Anderson, 2002). |
Pearson |
Numeric, the Pearson correlation coefficient between the two traits across all tips and across all trees. For binary traits this is also known as "Matthew's correlation coefficient" or "Phi coefficient". Note that for non-binary traits without a clear quantitative interpretation the Pearson correlation may not be meaningful, and the Spearman correlation or normalized mutual information may be more suitable. |
Spearman |
Numeric, the Spearman rank correlation coefficient between the two traits across all tips and across all trees. Note that for non-ordinal traits, i.e., without a clear ranking order, the Spearman correlation may not be meaningful, and the normalized mutual information may be more suitable. |
NMI |
Numeric, the mutual information between the two traits across all tips and across all trees, normalized by the square root of the product of entropies. In contrast to the raw mutual information, this normalized version is guaranteed to be between 0 (statistical independence) and 1 (full functional dependence). In contrast to the Pearson and Spearman correlations, the NMI is also suitable for comparing nominal categorical traits, i.e., that lack a quantitative interpretation and ranking order (e.g., beak color or cell shape). |
LRT |
The likelihood ratio test statistic, defined as |
Pearson_P1 |
Numeric, the one-sided statistical significance of the Pearson correlation, i.e., the estimated probability under the null model that the Pearson correlation would be smaller than the value obtained for the input data (if the latter is negative) or larger than the value obtained for the input data (if the latter is positive). Only available if |
Pearson_P2 |
Numeric, the two-sided statistical significance of the Pearson correlation, i.e., the estimated probability under the null model that the modulus of the Pearson correlation would be larger than observed for the input data. Only available if |
Pearson_mean_null |
Numeric, the average Pearson correlation expected under the null model. Only available if |
Pearson_std_null |
Numeric, the standard deviation of the Pearson correlation under the null model. Only available if |
Pearson_sims |
Numeric vector of length |
Pearson_P1_naive |
Numeric, the one-sided statistical significance of the Pearson correlation under a naive null hypothesis that ignores evolutionary relationships, i.e., under random permutation of the tips regardless of their location in the trees. This should NOT be used for any serious inference of trait dependencies; it is merely provided for comparison purposes, for example to check how much evolutionary relationships impact significance estimates. Only available if |
Pearson_P2_naive |
Numeric, the two-sided statistical significance of the Pearson correlation under a naive null hypothesis that ignores evolutionary relationships, i.e., under random permutation of the tips regardless of their location in the trees. This should NOT be used for any serious inference of trait dependencies; it is merely provided for comparison purposes, for example to check how much evolutionary relationships impact significance estimates. Only available if |
Spearman_P1, Spearman_mean_null, Spearman_std_null, Spearman_sims, Spearman_P1_naive, Spearman_P2_naive |
Similar to the values returned for the Pearson correlation, but referring to the Spearman rank correlation. |
NMI_P1, NMI_mean_null, NMI_std_null, NMI_sims, NMI_P1_naive |
Similar to the values returned for the Pearson correlation, but referring to the normalized mutual information. |
LRT_P1, LRT_mean_null, LRT_std_null, LRT_sims |
Similar to the values returned for the Pearson correlation, but referring to the likelihood ratio test statistic. |
LRT_P1_chi2 |
Numeric, the chi2-approximation analytical of the one-sided significance of the LRT. This approximation is only accurate asymptotically in the limit of infinite data, and only for the homogeneous models ( |
LRT_df |
Integer, the degrees of freedom of the asymptotic chi2-approximation of the LRT. This is the difference in the number of free parameters between the full and null model. |
Stilianos Louca
J. D. Boyko, J. M. Beaulieu (2023). Reducing the biases in false correlations between discrete characters. Systematic Biology. 72:476-488.
K. P. Burnham & D. R. Anderson (2002). Model Selection and Multimodel Inference. Springer.
M. Pagel (1994). Detecting correlated evolution on phylogenies: a general method for the comparative analysis of discrete characters. Proceedings of the Royal Society of London B. 255:37-45.
A. Strehl & J. Ghosh (2002). Cluster ensembles - a knowledge reuse framework for combining multiple partitions. Journal of Machine Learning Research. 3:583-617.
fit_mk,
simulate_mk_model,
correlate_phylo_geodistances
# EXAMPLE 1: Independent traits on one tree, homogeneous models
# generate a tree
Ntips = 100
tree = generate_random_tree(list(birth_rate_factor=0.1),max_tips=Ntips)$tree
# generate states for two independent categorical traits on all tips
# by simulating Mk models
# One trait has 3 states, the other has two states
Q1 = get_random_mk_transition_matrix(Nstates=3, rate_model="ARD", max_rate=1)
Q2 = get_random_mk_transition_matrix(Nstates=2, rate_model="ARD", max_rate=1)
tip_states1 = simulate_mk_model(tree, Q1, Nsimulations=1)$tip_states
tip_states2 = simulate_mk_model(tree, Q2, Nsimulations=1)$tip_states
# analyze correlations between the two traits
correlations = correlate_categorical_traits(trees = tree,
tip_states1 = tip_states1,
tip_states2 = tip_states2,
Nthreads = 1)
# print normalized mutual information and its one-sided P value
print(correlations$NMI)
print(correlations$NMI_P1)
######################################################################
# EXAMPLE 2: Co-dependent traits on multiple trees, homogeneous models
# generate multiple trees
Ntips = 100
Ntrees= 3
trees = lapply(seq_len(Ntrees), FUN=function(tr)
{ generate_random_tree(list(birth_rate_factor=0.1),max_tips=Ntips)$tree})
# simulate two binary trates influencing each other's transition rates
Q = get_random_mk_transition_matrix(Nstates=4, rate_model="ARD", max_rate=0.02)
state_combos = lapply(seq_len(Ntrees), FUN=function(tr)
simulate_mk_model(trees[[tr]], Q, Nsimulations=1)$tip_states)
tip_states1 = lapply(seq_len(Ntrees), FUN=function(tr)
{ 1L + ((state_combos[[tr]]==2) | (state_combos[[tr]]==4))} )
tip_states2 = lapply(seq_len(Ntrees), FUN=function(tr)
{ 1L + ((state_combos[[tr]]==3) | (state_combos[[tr]]==4))} )
# set some states in the to NA to simulate missing trait observations
tip_states1[[1]][c(1,3)] = NA
tip_states2[[2]][c(5,6)] = NA
# analyze correlations between the two traits
correlations = correlate_categorical_traits(trees = trees,
tip_states1 = tip_states1,
tip_states2 = tip_states2,
Nthreads = 1)
# print Pearson correlation and its two-sided P value
print(correlations$Pearson)
print(correlations$Pearson_P2)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.