Cultural evolution analysis

LBH song type prevalence and degradation

Author
Published

December 13, 2023

Source code and data found at https://github.com/maRce10/lbh_songtype_prevalence_and_degradation

1 Purpose

  • Depict the effet of cultural evolution on song structure variation in long-billed hermits

2 Load packages

Code
# knitr is require for creating html/pdf/word reports formatR is
# used for soft-wrapping code

# install/ load packages
sketchy::load_packages(packages = c("knitr", "formatR", "rprojroot",
    github = "maRce10/warbleR", github = "maRce10/baRulho", "readxl",
    "Rraven", "ggplot2", "brms", "viridis", "corrplot", "DT", "ape",
    "phangorn", "ggtree", "phytools", "ratematrix", "geomorph", "evolvability",
    "geiger", "ggdist", "gghalves"))

3 Extract SUR tree

Code
trees <- read.tree("/home/m/Dropbox/Projects/lbh_cultural_evolution_revBayes/output/most_recent_revbayes_models/SUR_prank_old_early_global_219792.trees")

# mcct <- mcc(x = tre)


tree_sty <- unique(unlist(lapply(trees, "[", "tip.label")))

ntips_trees <- sapply(trees, Ntip)

tree <- trees[[which.max(ntips_trees)]]


# #Highlight and label clade ggtree(tree, layout = 'fan', size =
# 2) + geom_nodelab(col= 'red', hjust = 2) + geom_tiplab(size=3,
# offset=0.1)

sur_dat <- read.csv("./data/raw/allsongsSUR.csv")

sur_dat <- sur_dat[grep("marker|measu", sur_dat$song.type, invert = TRUE),
    ]

sur_dat$song.type.year <- paste(sur_dat$song.type, sur_dat$year, sep = "-")
# unique(sur_dat$song.type.year)

sur_dat <- sur_dat[sur_dat$song.type.year %in% tree_sty, ]

sty <- unique(sur_dat$song.type.year)

trees <- lapply(trees, function(x) drop.tip(x, tip = setdiff(x$tip.label,
    sty)))

# unique(unlist(lapply(trees, '[', 'tip.label')))

ntips_trees <- sapply(trees, Ntip)

tree <- trees[[which.max(ntips_trees)]]

ggtree(tree, layout = "fan", size = 2) + geom_nodelab(col = "red",
    hjust = 2) + geom_tiplab(size = 3, offset = 0.1)
Code
ultra_tree <- ape::chronoMPL(tree)

ggtree(ultra_tree, layout = "fan", size = 2, options(ignore.negative.edge = TRUE)) +
    geom_nodelab(col = "red", hjust = 2) + geom_tiplab(size = 3, offset = 0.1)

4 Measure acoustic structure

Code
est <- readRDS("./data/raw/extended_selection_table_all_songtype_high_snr.RDS")

est$song.type.year <- paste(est$lek.song.type, est$year, sep = "-")

est <- est[est$song.type.year %in% sty, ]

table(table(est$song.type.year))

 1  2  3 
13  2 18 
Code
spec_features <- spectro_analysis(est, wl = 200, ovlp = 90)
spec_features$song.type.year <- est$song.type.year
spec_features$org.sound.files <- est$sound.files
spec_features$SNR <- est$SNR

# read fundamental freq contour data fund_contours <-
# read.csv('./data/raw/seltailor_output.csv') cs <-
# check_sels(fund_contours, fix.selec = T, path = './data/raw')
# fund_contours <- fund_contours[cs$check.res == 'OK',]
# contour_id <- imp_raven(path = './data/raw/', files =
# '44kKz_songtype_segment_analysis_sep_2019.txt', warbler.format
# = TRUE, all.data = TRUE) contour_id$song.type.year <-
# paste(contour_id$lek.song.type, contour_id$year, sep = '-')
# contour_id$song.type.year.sfs <-
# paste(contour_id$lek.song.type, contour_id$year,
# contour_id$sf.selec, sep = '-')
# all(table(contour_id$song.type.year.sfs) == 20) spid <-
# song_param(contour_id[, c(1:6, ncol(contour_id))], song_colm =
# 'song.type.year.sfs') spid$song.type.year <-
# sapply(spid$song.type.year.sfs, function(x)
# contour_id$song.type.year[contour_id$song.type.year.sfs ==
# x][1]) colms <- c('sound.files', 'start', 'end', 'selec',
# 'song.type.year.sfs', 'song.type.year')

# fund_contours$song.type.year <-
# sapply(seq_len(nrow(fund_contours)), function(x){ Y <-
# fund_contours[x, c('sound.files', 'start', 'end', 'selec')] Z
# <- spid[, c('sound.files', 'start', 'end', 'selec',
# 'song.type.year.sfs', 'song.type.year')] Y$song.type.year.sfs
# <- NA Y$song.type.year.sfs <-
# as.character(Y$song.type.year.sfs) Y$song.type.year <- NA
# Y$song.type.year <- as.character(Y$song.type.year) Y$source <-
# 'contours' Z$source <- 'IDs' X <- rbind(Y, Z) ovlp <-
# overlapping_sels(X, indx.row = TRUE, pb = FALSE, verbose =
# FALSE) sty <-
# ovlp$song.type.year[!is.na(ovlp$song.type.year.sfs) &
# !is.na(ovlp$indx.row)] return(sty) }) spec_features$song.type
# <- substr(spec_features$song.type.year, 0, 6)
# fund_contours$song.type <-
# substr(fund_contours$song.type.year, 0, 6)

# spec_features$meanfun <- sapply(spec_features$song.type,
# function(x){ X <- fund_contours[fund_contours$song.type == x,
# ] meanfun <- mean(unlist(X[,grep('ff', names(X))]))
# return(meanfun) }) spec_features$minfun <-
# sapply(spec_features$song.type, function(x){ X <-
# fund_contours[fund_contours$song.type == x, ] minfun <-
# min(unlist(X[,grep('ff', names(X))])) return(minfun) })

5 Phylogenetic analyses

5.1 Phylogenetic signal

Code
features <- c("meandom", "mindom", "maxdom", "dfrange", "sp.ent",
    "modindx", "duration", "skew", "kurt", "time.ent", "time.IQR",
    "meanpeakf")

spec_features <- spec_features[, c("sound.files", "selec", "song.type.year",
    "org.sound.files", "SNR", features)]

mean_spec_features <- aggregate(x = . ~ song.type.year, spec_features[,
    c("song.type.year", features)], mean)

# add standard error
se_spec_features <- aggregate(x = . ~ song.type.year, spec_features[,
    c("song.type.year", features)], function(x) sd(x)/sqrt(length(x)))

for (i in features) se_spec_features[is.na(se_spec_features[, i]),
    i] <- mean(se_spec_features[, i], na.rm = TRUE)


out <- lapply(features, function(x) {

    trait <- mean_spec_features[, x]
    # trait_se <- se_spec_features[, x]

    # names(trait_se) <-
    names(trait) <- mean_spec_features$song.type.year

    ps <- phylosig(tree = tree, x = trait, method = "lambda", test = TRUE)

    out_df <- data.frame(feature = x, as.data.frame(ps[1:4]))

    return(out_df)
})


phylosig_df <- do.call(rbind, out)

phylosig_df$lambda <- round(phylosig_df$lambda, 2)

phylosig_df[order(phylosig_df$lambda), ]
feature lambda logL logL0 P
3 maxdom 0.00 -49.87925 -49.87867 1.0000000
4 dfrange 0.00 -55.89417 -55.89400 1.0000000
6 modindx 0.00 -77.84348 -77.84286 1.0000000
12 meanpeakf 0.00 -56.19731 -56.19693 1.0000000
7 duration 0.16 90.97903 90.48411 0.3197809
8 skew 0.24 -39.79507 -40.01873 0.5036099
2 mindom 0.25 -45.85286 -46.79134 0.1706793
10 time.ent 0.26 145.65136 144.92847 0.2292064
5 sp.ent 0.37 67.33066 65.10486 0.0348684
9 kurt 0.42 -109.40088 -109.55856 0.5744056
11 time.IQR 0.44 116.85830 116.03394 0.1991345
1 meandom 0.66 -44.64417 -47.08116 0.0272644

5.2 Phenograms by acoustic feature

Code
sub_features <- c(Modulation = "modindx", `Max dominant` = "maxdom",
    `Frequency range` = "dfrange", `Mean frequency` = "meandom", `Time IQR` = "time.IQR",
    Kurtosis = "kurt")


cols <- viridis(10)[c(3, 7)]

par(mfcol = c(3, 2))

for (i in seq_along(sub_features)) {

    feat <- mean_spec_features[, sub_features[i]]

    feat <- scale(feat)

    names(feat) <- mean_spec_features$song.type.year

    phenogram(tree, x = feat, spread.labels = F, offset = 0, ftype = "off",
        colors = ifelse(i < 4, cols[1], cols[2]), ylim = c(-2.4, 2.4))

    title(names(sub_features)[i], cex.main = 2)
}

5.3 Multivariate phylogenetic signal

Code
library(mvMORPH)

mean_spec_features_matrix <- as.matrix(mean_spec_features[, 2:ncol(mean_spec_features)])

rownames(mean_spec_features_matrix) <- mean_spec_features$song.type.year

dat <- list(Y = mean_spec_features_matrix)

signal <- mvgls(Y ~ 1, data = dat, tree, model = "lambda", penalty = "RidgeArch")

summary(signal)

Call:
mvgls(formula = Y ~ 1, data = dat, tree = tree, model = "lambda", 
    penalty = "RidgeArch")


Generalized least squares fit by penalized REML 
        GIC   logLik
  -625.5474 384.4835

Parameter estimate(s):
lambda: 0.2947 

Regularization parameter (gamma): 0 


Covariance matrix of size: 12 by 12 
for 33 observations 

Coefficients (truncated):
            meandom mindom maxdom dfrange sp.ent modindx duration  skew kurt
(Intercept)   5.488  2.726  8.125   5.399 0.9063   10.84   0.1417 2.702 13.6
            time.ent
(Intercept)   0.8912
Use "coef" to display all the coefficients

5.4 Modes of evolution

Code
models <- c(brownian_motion = "BM", Ornstein_Uhlenbeck = "OU", early_burst = "EB",
    rate_trend = "rate_trend", puntctuational = "kappa", time_dependent = "delta",
    white = "white")

out <- warbleR:::pblapply_wrblr_int(features, cl = 10, function(x) {

    trait <- mean_spec_features[, x]
    # trait_se <- se_spec_features[, x]

    names(trait) <- mean_spec_features$song.type.year

    mods <- lapply(models, function(y) {

        fc <- fitContinuous(phy = tree, dat = trait, model = y)

        out <- data.frame(feature = x, model = y, AICc = fc$opt$aicc,
            alpha = ifelse(length(fc$opt$alpha) > 0, fc$opt$alpha,
                NA))

        return(out)
    })

    out_df <- do.call(rbind, mods)

    return(out_df)
})


evo_mods <- do.call(rbind, out)

write.csv(evo_mods, "./data/processed/evolutionary_models_by_feature.csv",
    row.names = FALSE)
Code
evo_mods <- read.csv("./data/processed/evolutionary_models_by_feature.csv")

ou_evo <- evo_mods[evo_mods$model == "OU", ]

out <- warbleR:::pblapply_wrblr_int(1:nrow(ou_evo), cl = 10, function(x) {

    trait <- mean_spec_features[, ou_evo$feature[x]]
    # trait_se <- se_spec_features[, x]

    names(trait) <- mean_spec_features$song.type.year

    cou <- compar.ou(trait, tree, alpha = ou_evo$alpha[x])

    out_df <- data.frame(feature = ou_evo$feature[x], ou_opt = cou$para[2,
        1])
    return(out_df)
})


ou_opts <- do.call(rbind, out)


spec_features$year <- as.numeric(substr(spec_features$song.type.year,
    8, 11))



agg_feat_by_year <- aggregate(. ~ year, spec_features[, c("year",
    features)], mean)


stck_feat_by_year <- stack(agg_feat_by_year)

stck_feat_by_year <- stck_feat_by_year[stck_feat_by_year$ind != "year",
    ]
stck_feat_by_year$year <- agg_feat_by_year$year


ggplot(stck_feat_by_year, aes(x = year, y = values)) + geom_line() +
    theme_classic(base_size = 20) + facet_wrap(~ind, scales = "free_y")
Code
evo_mods <- read.csv("./data/processed/evolutionary_models_by_feature.csv")

evo_mods <- evo_mods[order(evo_mods$feature, evo_mods$AICc), ]

out <- lapply(unique(evo_mods$feature), function(x) {
    X <- evo_mods[evo_mods$feature == x, ]

    X <- X[X$AICc <= min(X$AICc) + 4, ]

    return(X)
})

do.call(rbind, out)
feature model AICc alpha
28 dfrange white 118.11993 NA
23 dfrange OU 118.55581 0.1415737
49 duration white -172.58969 NA
44 duration OU -170.16211 2.7182818
63 kurt white 222.15864 NA
58 kurt OU 224.21211 0.1376262
21 maxdom white 100.54426 NA
16 maxdom OU 101.75903 0.1782065
2 meandom OU 86.73243 0.0581166
84 meanpeakf white 111.74744 NA
79 meanpeakf OU 113.31265 0.1728527
14 mindom white 99.05904 NA
9 mindom OU 99.31139 0.1265486
42 modindx white 161.54394 NA
37 modindx OU 163.78033 0.2568796
56 skew white 83.75584 NA
51 skew OU 84.47327 0.0863016
30 sp.ent OU -125.80764 0.0799415
35 sp.ent white -122.97104 NA
70 time.ent white -282.66898 NA
65 time.ent OU -280.24139 2.7182818
77 time.IQR white -225.28922 NA
72 time.IQR OU -222.86163 2.7182818
Code
out <- lapply(unique(evo_mods$feature), function(x) {
    X <- evo_mods[evo_mods$feature == x, ]
    X$delta_aicc <- X$AICc - min(X$AICc)
    X$delta_aicc <- X$delta_aicc
    return(X)
})

evo_delta_aic <- do.call(rbind, out)

restricted <- c("meandom", "mindom", "maxdom", "dfrange", "sp.ent",
    "meanpeakf")

evo_delta_aic$restriction <- ifelse(evo_delta_aic$feature %in% restricted,
    "restricted", "unrestricted")

agg_delta_aicc <- aggregate(delta_aicc ~ model + restriction, evo_delta_aic,
    mean)


# agg_delta_aicc$delta_aicc <- agg_delta_aicc$delta_aicc * -1

agg_delta_aicc <- agg_delta_aicc[agg_delta_aicc$model != "white",
    ]

ggplot(agg_delta_aicc, aes(x = model, y = delta_aicc, fill = restriction)) +
    geom_bar(stat = "identity", position = "dodge") + scale_fill_viridis_d(begin = 0.2,
    end = 0.8, alpha = 0.6) + theme_classic(base_size = 20) + labs(x = "Evolutionary model",
    y = "Delta AICc", fill = "Morphological\nrestriction")

5.5 Coevolution

Code
mean_spec_features_matrix <- as.matrix(mean_spec_features[, 2:ncol(mean_spec_features)])

rownames(mean_spec_features_matrix) <- mean_spec_features$song.type.year
Code
## Run multiple MCMC chains.
handle_1 <- ratematrixMCMC(data = mean_spec_features_matrix, phy = tree,
    gen = 30000, dir = tempdir())

handle_2 <- ratematrixMCMC(data = mean_spec_features_matrix, phy = tree,
    gen = 30000, dir = tempdir())

## Read both chains:
posterior_1 <- readMCMC(handle_1, burn = 0.2, thin = 1)
posterior_2 <- readMCMC(handle_2, burn = 0.2, thin = 1)
## Check for convergence checkConvergence(posterior_1,
## posterior_2) Merge all posteriors in the list.
merged.posterior <- mergePosterior(posterior_1, posterior_2)

# length(merged.posterior$matrix)

# str(merged.posterior$matrix[[1]])


mean_cov <- merged.posterior$matrix[[1]]
for (i in 2:length(merged.posterior$matrix)) mean_cov <- mean_cov +
    merged.posterior$matrix[[i]]

mean_cov <- mean_cov/length(merged.posterior$matrix)

# range(mean_cov)

mean_corr <- cov2cor(mean_cov)
colnames(mean_corr) <- paste(names(mean_spec_features)[-1], c(1, 1,
    1, 1, 1, 0, 0, 0, 0, 0, 0, 1))


cols_corr <- colorRampPalette(c(viridis(3, direction = 1, begin = 0.2,
    end = 0.5), "#BEBEBE1A", "white", "#BEBEBE1A", viridis(3, direction = 1,
    begin = 0.7, end = 0.9)))(30)

cp <- corrplot.mixed(mean_corr, tl.cex = 0.7, upper.col = cols_corr,
    lower.col = cols_corr, order = "hclust", lower = "number", upper = "ellipse",
    tl.col = "black")

## Plot results: plotRatematrix(merged.posterior)

5.6 Compare evolutionary rates of acoustic features

Code
feat_grp <- c(1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1)
names(feat_grp) <- colnames(mean_spec_features_matrix)

EMR2 <- compare.multi.evol.rates(A = mean_spec_features_matrix, gp = feat_grp,
    Subset = TRUE, phy = tree, iter = 10000, print.progress = FALSE)

EMR2

Call:


Observed Rate Ratio: 6.72984

P-value: 1e-04

Effect Size: 2.83204

Based on 10001 random permutations

The rate for group 0 is 0.675139810269116  

The rate for group 1 is 0.100320309806049 

5.7 Jacknife evolutionary rate intervals

Code
# get confidence intervals

out <- warbleR:::pblapply_wrblr_int(1:50, cl = 20, function(x) {

    tips <- sample(tree$tip.label, 4)

    sub_tree <- drop.tip(tree, tip = tips)
    sub_mat <- mean_spec_features_matrix[!row.names(mean_spec_features_matrix) %in%
        tips, ]

    jck_EMR <- compare.multi.evol.rates(A = sub_mat, gp = feat_grp,
        Subset = TRUE, phy = sub_tree, iter = 10000, print.progress = FALSE)

    return(jck_EMR$sigma.d.gp)
})

jck_evo_rates <- as.data.frame(do.call(rbind, out))

names(jck_evo_rates) <- c("Unrestricted", "Restricted")

jck_evo_rates <- stack(jck_evo_rates)

write.csv(jck_evo_rates, "./data/processed/evolutionary_rate_jacknife.csv",
    row.names = FALSE)
Code
jck_evo_rates <- read.csv("./data/processed/evolutionary_rate_jacknife.csv")

cols <- viridis(10)

# raincoud plot:
fill_color <- adjustcolor(cols[[6]], 0.4)

ggplot(jck_evo_rates, aes(y = values, x = ind)) +
  # add half-violin from {ggdist} package
  stat_halfeye(
    fill = fill_color,
    alpha = 0.5,
    # custom bandwidth
    adjust = .5,
    # adjust height
    width = .6,
    .width = 0,
    # move geom to the cright
    justification = -.2,
    point_colour = NA
  ) +
  geom_boxplot(fill = fill_color,
    width = .15,
    # remove outliers
    outlier.shape = NA # `outlier.shape = NA` works as well
  ) +
  # add justified jitter from the {gghalves} package
  geom_half_point(
    color = fill_color,
    # draw jitter on the left
    side = "l",
    # control range of jitter
    range_scale = .4,
    # add some transparency
    alpha = .5,
  ) +
   # ylim(c(-30, 310)) +
  labs(x = "Acoustic features", y = "Evolutionary rate") + theme(axis.text.x = element_text(angle = 15, hjust = 1)) + 
    theme_classic(base_size = 20)

5.8 Evolutionary integration

Code
feat_grp <- c(1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1)
IT <- phylo.integration(A = mean_spec_features_matrix, partition.gp = feat_grp,
    phy = tree, iter = 10000, print.progress = FALSE)


summary(IT)  # Test summary

Call:
phylo.integration(A = mean_spec_features_matrix, phy = tree,  
    partition.gp = feat_grp, iter = 10000, print.progress = FALSE) 



r-PLS: 0.29

Effect Size (Z): -0.11624

P-value: 0.5490451

Based on 10001 random permutations
Code
# plot(IT) # PLS plot

5.9 Degradation and evolutionary rate of acoustic features

5.9.1 PCA

Code
# Taking only numeric data for the pca
degrad_df <- read.csv("./data/processed/degradation_measures_SUR_ALL.csv")

degrad_params <- c("signal.to.noise.ratio", "tail.to.signal.ratio",
    "excess.attenuation", "envelope.correlation", "blur.ratio", "cross.correlation",
    "spectrum.blur.ratio", "spectrum.correlation")

degrad_df <- degrad_df[complete.cases(degrad_df[, degrad_params]),
    ]

sapply(degrad_df[, degrad_params], function(x) any(is.infinite(x)))
signal.to.noise.ratio  tail.to.signal.ratio    excess.attenuation 
                FALSE                 FALSE                  TRUE 
 envelope.correlation            blur.ratio     cross.correlation 
                FALSE                 FALSE                 FALSE 
  spectrum.blur.ratio  spectrum.correlation 
                FALSE                 FALSE 
Code
degrad_df <- degrad_df[!is.infinite(degrad_df$excess.attenuation),
    ]

pca_degrad <- prcomp(degrad_df[, degrad_params], scale = T)

pca_var <- round(summary(pca_degrad)$importance[2, ] * 100)

degrad_df$pc1 <- pca_degrad$x[, 1]

degrad_params <- c(degrad_params, "pc1")
# plot rotation values by PC
pca_rot <- as.data.frame(pca_degrad$rotation[, 1:4])

pca_rot_stck <- stack(pca_rot)

pca_rot_stck$variable <- rownames(pca_rot)
pca_rot_stck$values[pca_rot_stck$ind == "PC1"] <- pca_rot_stck$values[pca_rot_stck$ind ==
    "PC1"]
pca_rot_stck$Sign <- ifelse(pca_rot_stck$values > 0, "Positive", "Negative")
pca_rot_stck$rotation <- abs(pca_rot_stck$values)
pca_rot_stck$ind_var <- paste0(pca_rot_stck$ind, " (", sapply(pca_rot_stck$ind,
    function(x) pca_var[names(pca_var) == x]), "%)")

ggplot(pca_rot_stck, aes(x = variable, y = rotation, fill = Sign)) +
    geom_col() + coord_flip() + scale_fill_viridis_d(alpha = 0.7,
    begin = 0.2, end = 0.8) + facet_wrap(~ind_var) + theme_classic()

5.10 Estimate evolutinary rate association to degradation

Code
mean_spec_features$pc1 <- sapply(mean_spec_features$song.type.year,
    function(x) mean(degrad_df$pc1[degrad_df$song.type.year == x]))



# Standardize the tree to unit length
ultra_tree_standardized <- multi2di(ultra_tree)
ultra_tree_standardized <- compute.brlen(ultra_tree_standardized,
    method = "cladewise")

mods <- warbleR:::pblapply_wrblr_int(2:ncol(mean_spec_features), cl = 10,
    function(x) {
        # brownian motion
        bm_mod <- rate_gls(x = mean_spec_features$pc1, y = mean_spec_features[,
            x], species = mean_spec_features$song.type.year, ultra_tree_standardized,
            model = "predictor_BM", silent = TRUE, maxiter = 1000)

        bootout_bm <- rate_gls_boot(bm_mod, n = 100, silent = TRUE,
            maxiter = 1000)

        bootout_bm <- cbind(model = "BM", feature = names(mean_spec_features)[x],
            parameter = rownames(bootout_bm$summary), as.data.frame(bootout_bm$summary))

        # geometric brownian motion
        gbm_mod <- rate_gls(x = mean_spec_features$pc1 + 1, y = mean_spec_features[,
            x], species = mean_spec_features$song.type.year, ultra_tree_standardized,
            model = "predictor_gBM", silent = TRUE, maxiter = 1000)

        bootout_gbm <- rate_gls_boot(gbm_mod, n = 100, silent = TRUE,
            maxiter = 1000)

        bootout_gbm <- cbind(model = "gBM", feature = names(mean_spec_features)[x],
            parameter = rownames(bootout_gbm$summary), as.data.frame(bootout_gbm$summary))

        re_mod <- rate_gls(x = mean_spec_features$pc1, y = mean_spec_features[,
            x], species = mean_spec_features$song.type.year, ultra_tree_standardized,
            model = "recent_evol", silent = TRUE, maxiter = 1000)

        bootout_re <- rate_gls_boot(re_mod, n = 100, silent = TRUE,
            maxiter = 1000)

        bootout_re <- cbind(model = "recent_evol", feature = names(mean_spec_features)[x],
            parameter = rownames(bootout_re$summary), as.data.frame(bootout_re$summary))

        bootout <- rbind(bootout_bm, bootout_gbm, bootout_re)

        return(bootout)
    })

gls_res <- do.call(rbind, mods)

write.csv(gls_res, "./data/processed/evolutionary_rate_by_degradation.csv",
    row.names = FALSE)
Code
gls_res <- read.csv("./data/processed/evolutionary_rate_by_degradation.csv")

gls_res <- gls_res[gls_res$parameter == "b" | gls_res$parameter ==
    "Rsquared", c("model", "feature", "parameter", "Estimate", "SE",
    "X2.5.", "X97.5.")]

gls_res_kbl <- kableExtra::kbl(gls_res, row.names = FALSE, escape = FALSE,
    format = "html", digits = 3)

gls_res_kbl <- kableExtra::row_spec(kable_input = gls_res_kbl, row = which(gls_res$`97.5%` *
    gls_res$`2.5%` > 0 & gls_res$parameter == "b"), background = grDevices::adjustcolor("#6DCD59FF",
    alpha.f = 0.3))

gls_res_kbl
model feature parameter Estimate SE X2.5. X97.5.
BM meandom b -1.727 6.478 -7.960 8.042
BM meandom Rsquared 0.002 NA 0.000 0.091
gBM meandom b -1.198 5.854 -7.603 4.771
gBM meandom Rsquared 0.001 NA 0.000 0.090
recent_evol meandom b -0.422 0.263 -1.030 0.402
recent_evol meandom Rsquared 0.076 NA 0.000 0.376
BM mindom b 3.289 18.729 -6.658 13.752
BM mindom Rsquared 0.001 NA 0.000 0.217
gBM mindom b 4.498 14.874 -2.105 61.114
gBM mindom Rsquared 0.003 NA 0.005 0.640
recent_evol mindom b 1.023 0.344 0.111 1.583
recent_evol mindom Rsquared 0.222 NA 0.022 0.432
BM maxdom b -8.240 17.585 -24.814 13.160
BM maxdom Rsquared 0.007 NA 0.000 0.095
gBM maxdom b -6.169 14.594 -23.030 6.257
gBM maxdom Rsquared 0.006 NA 0.000 0.085
recent_evol maxdom b -1.249 0.297 -1.638 0.107
recent_evol maxdom Rsquared 0.363 NA 0.003 0.492
BM dfrange b -4.729 21.663 -18.153 15.975
BM dfrange Rsquared 0.002 NA 0.000 0.123
gBM dfrange b -14.815 28.522 -31.707 29.440
gBM dfrange Rsquared 0.009 NA 0.000 0.109
recent_evol dfrange b 0.522 0.970 -2.142 3.357
recent_evol dfrange Rsquared 0.009 NA 0.000 0.356
BM sp.ent b 0.009 0.014 -0.010 0.024
BM sp.ent Rsquared 0.011 NA 0.000 0.218
gBM sp.ent b 0.010 0.012 -0.004 0.034
gBM sp.ent Rsquared 0.019 NA 0.002 0.770
recent_evol sp.ent b 0.001 0.000 0.000 0.001
recent_evol sp.ent Rsquared 0.356 NA 0.073 0.380
BM modindx b 58.418 78.962 -48.165 146.320
BM modindx Rsquared 0.017 NA 0.000 0.140
gBM modindx b 61.666 69.051 -7.437 488.068
gBM modindx Rsquared 0.025 NA 0.001 0.635
recent_evol modindx b 5.940 3.199 -2.769 11.465
recent_evol modindx Rsquared 0.100 NA 0.001 0.378
BM duration b 0.001 0.004 -0.002 0.004
BM duration Rsquared 0.001 NA 0.000 0.110
gBM duration b 0.001 0.003 0.000 0.004
gBM duration Rsquared 0.002 NA 0.000 0.570
recent_evol duration b 0.000 0.000 0.000 0.001
recent_evol duration Rsquared 0.126 NA 0.002 0.367
BM skew b -5.277 8.756 -18.343 7.859
BM skew Rsquared 0.012 NA 0.000 0.168
gBM skew b -3.019 7.473 -12.053 9.595
gBM skew Rsquared 0.005 NA 0.000 0.082
recent_evol skew b -0.058 0.412 -0.776 0.792
recent_evol skew Rsquared 0.001 NA 0.000 0.278
BM kurt b -366.025 569.299 -839.237 353.048
BM kurt Rsquared 0.013 NA 0.000 0.145
gBM kurt b -205.048 489.805 -664.046 509.046
gBM kurt Rsquared 0.006 NA 0.000 0.093
recent_evol kurt b -3.547 30.350 -50.642 45.737
recent_evol kurt Rsquared 0.000 NA 0.000 0.342
BM time.ent b 0.000 0.000 0.000 0.000
BM time.ent Rsquared 0.000 NA 0.000 0.121
gBM time.ent b 0.000 0.000 0.000 0.000
gBM time.ent Rsquared 0.000 NA 0.000 0.115
recent_evol time.ent b 0.000 0.000 0.000 0.000
recent_evol time.ent Rsquared 0.042 NA 0.000 0.251
BM time.IQR b 0.000 0.001 -0.001 0.001
BM time.IQR Rsquared 0.004 NA 0.000 0.124
gBM time.IQR b 0.000 0.001 0.000 0.002
gBM time.IQR Rsquared 0.006 NA 0.000 0.533
recent_evol time.IQR b 0.000 0.000 0.000 0.000
recent_evol time.IQR Rsquared 0.026 NA 0.000 0.175
BM meanpeakf b 5.881 19.215 -9.870 25.909
BM meanpeakf Rsquared 0.003 NA 0.000 0.119
gBM meanpeakf b 3.524 15.902 -6.365 22.135
gBM meanpeakf Rsquared 0.002 NA 0.000 0.254
recent_evol meanpeakf b -0.632 0.827 -2.298 1.074
recent_evol meanpeakf Rsquared 0.018 NA 0.000 0.378
BM pc1 b 1.216 1.431 -1.250 3.247
BM pc1 Rsquared 0.023 NA 0.000 0.096
gBM pc1 b 1.291 1.279 -0.055 9.022
gBM pc1 Rsquared 0.032 NA 0.001 0.536
recent_evol pc1 b 0.000 0.068 -0.150 0.177
recent_evol pc1 Rsquared 0.000 NA 0.000 0.335

Takeaways

 


 

Session information

R version 4.3.1 (2023-06-16)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.2 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3 
LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3;  LAPACK version 3.9.0

locale:
 [1] LC_CTYPE=pt_BR.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=es_CR.UTF-8        LC_COLLATE=pt_BR.UTF-8    
 [5] LC_MONETARY=es_CR.UTF-8    LC_MESSAGES=pt_BR.UTF-8   
 [7] LC_PAPER=es_CR.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=es_CR.UTF-8 LC_IDENTIFICATION=C       

time zone: America/Costa_Rica
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] mvMORPH_1.1.7      subplex_1.8        corpcor_1.6.10     gghalves_0.1.4    
 [5] ggdist_3.3.0       geiger_2.0.11      evolvability_2.0.0 geomorph_4.0.6    
 [9] Matrix_1.6-2       rgl_1.2.1          RRPP_1.4.0         ratematrix_1.2.4  
[13] phytools_1.9-16    maps_3.4.1.1       ggtree_3.8.2       phangorn_2.11.1   
[17] ape_5.7-1          DT_0.30            corrplot_0.92      viridis_0.6.4     
[21] viridisLite_0.4.2  brms_2.20.4        Rcpp_1.0.11        ggplot2_3.4.4     
[25] Rraven_1.0.14      readxl_1.4.3       baRulho_2.1.0      ohun_1.0.0        
[29] warbleR_1.1.29     NatureSounds_1.0.4 seewave_2.2.3      tuneR_1.4.5       
[33] rprojroot_2.0.4    formatR_1.14       knitr_1.45        

loaded via a namespace (and not attached):
  [1] fs_1.6.3                matrixStats_1.1.0       bitops_1.0-7           
  [4] sf_1.0-14               webshot_0.5.5           httr_1.4.7             
  [7] doParallel_1.0.17       numDeriv_2016.8-1.1     tools_4.3.1            
 [10] backports_1.4.1         utf8_1.2.4              R6_2.5.1               
 [13] lazyeval_0.2.2          withr_2.5.2             Brobdingnag_1.2-9      
 [16] prettyunits_1.2.0       gridExtra_2.3           soundgen_2.6.1         
 [19] cli_3.6.1               shinyjs_2.1.0           labeling_0.4.3         
 [22] mvtnorm_1.2-3           readr_2.1.4             proxy_0.4-27           
 [25] dtw_1.23-1              pbapply_1.7-2           QuickJSR_1.0.7         
 [28] systemfonts_1.0.5       yulab.utils_0.1.0       StanHeaders_2.26.28    
 [31] svglite_2.1.2           parallelly_1.36.0       plotrix_3.8-3          
 [34] rstudioapi_0.15.0       phylolm_2.6.2           optimParallel_1.0-2    
 [37] generics_0.1.3          gridGraphics_0.5-1      combinat_0.0-8         
 [40] gtools_3.9.4            crosstalk_1.2.0         dplyr_1.1.3            
 [43] distributional_0.3.2    inline_0.3.19           loo_2.6.0              
 [46] fansi_1.0.5             abind_1.4-5             lifecycle_1.0.4        
 [49] scatterplot3d_0.3-44    yaml_2.3.7              clusterGeneration_1.3.8
 [52] grid_4.3.1              promises_1.2.1          crayon_1.5.2           
 [55] miniUI_0.1.1.1          lattice_0.22-5          pillar_1.9.0           
 [58] boot_1.3-28.1           rjson_0.2.21            estimability_1.4.1     
 [61] fftw_1.0-7              shinystan_2.6.0         future.apply_1.11.0    
 [64] codetools_0.2-19        fastmatch_1.1-4         glue_1.6.2             
 [67] packrat_0.9.2           ggfun_0.1.3             remotes_2.4.2.1        
 [70] vctrs_0.6.4             png_0.1-8               treeio_1.24.3          
 [73] spam_2.10-0             testthat_3.2.0          cellranger_1.1.0       
 [76] gtable_0.3.4            cachem_1.0.8            xfun_0.41              
 [79] mime_0.12               coda_0.19-4             signal_0.7-7           
 [82] iterators_1.0.14        sketchy_1.0.2           pbmcapply_1.5.1        
 [85] shinythemes_1.2.0       units_0.8-4             ellipsis_0.3.2         
 [88] nlme_3.1-163            xts_0.13.1              threejs_0.3.3          
 [91] rstan_2.32.3            tensorA_0.36.2          Deriv_4.1.3            
 [94] KernSmooth_2.23-22      colorspace_2.1-0        DBI_1.1.3              
 [97] mnormt_2.1.1            tidyselect_1.2.0        processx_3.8.2         
[100] emmeans_1.8.9           compiler_4.3.1          rvest_1.0.3            
[103] expm_0.999-7            xml2_1.3.5              colourpicker_1.3.0     
[106] posterior_1.5.0         checkmate_2.3.0         scales_1.2.1           
[109] dygraphs_1.1.1.6        classInt_0.4-10         quadprog_1.5-8         
[112] callr_3.7.3             stringr_1.5.0           digest_0.6.33          
[115] shinyBS_0.61.1          minqa_1.2.6             Sim.DiffProc_4.8       
[118] rmarkdown_2.25          jpeg_0.1-10             htmltools_0.5.7        
[121] pkgconfig_2.0.3         base64enc_0.1-3         lme4_1.1-35.1          
[124] fastmap_1.1.1           rlang_1.1.2             htmlwidgets_1.6.2      
[127] shiny_1.7.5.1           farver_2.1.1            zoo_1.8-12             
[130] jsonlite_1.8.7          RCurl_1.98-1.13         magrittr_2.0.3         
[133] kableExtra_1.3.4        ggplotify_0.1.2         dotCall64_1.1-0        
[136] bayesplot_1.10.0        patchwork_1.1.3         munsell_0.5.0          
[139] stringi_1.7.12          brio_1.1.3              MASS_7.3-60            
[142] plyr_1.8.9              pkgbuild_1.4.2          parallel_4.3.1         
[145] listenv_0.9.0           splines_4.3.1           hms_1.1.3              
[148] ps_1.7.5                igraph_1.5.1            markdown_1.11          
[151] reshape2_1.4.4          stats4_4.3.1            rstantools_2.3.1.1     
[154] evaluate_0.23           RcppParallel_5.1.7      deSolve_1.38           
[157] nloptr_2.0.3            tzdb_0.4.0              foreach_1.5.2          
[160] httpuv_1.6.12           tidyr_1.3.0             purrr_1.0.2            
[163] future_1.33.0           xtable_1.8-4            glassoFast_1.0.1       
[166] e1071_1.7-13            tidytree_0.4.5          later_1.3.1            
[169] class_7.3-22            tibble_3.2.1            aplot_0.2.2            
[172] memoise_2.0.1           globals_0.16.2          bridgesampling_1.1-2   
[175] xaringanExtra_0.7.0