If we have data on the longitudes and latitudes of taxa, sometimes it is useful to control for this spatial location to ensure that our model is capturing deep ancestral relationships rather than shared environmental effects or more recent diffusion among neighbours.
The lon_lat argument in the coev_fit()
function allows us to easily control for spatial proximity. This
argument takes a data frame of longitude and latitude coordinates (in
decimal degrees) for taxa on the phylogeny. If longitude and latitude
values are inputted by the user, the function calculates the Euclidean
distances between these points on a unit sphere and includes a Gaussian
process over these distances for each variable in the model.
When studying the coevolution of political and religious authority in Austronesian societies, we would like to ensure that our results are due to coevolution over deep cultural time rather than more recent borrowing among societies with close geographic proximity.
Here are the longitude and latitude values for the first five Austronesian societies:
# A tibble: 5 × 3
id latitude longitude
<chr> <dbl> <dbl>
1 Aiwoo -10.3 166.
2 Alune -3.1 128.
3 AnejomAneityum -20.2 170.
4 Anuta -11.6 170.
5 Atoni -9.7 124.
We can include these spatial coordinates in the model. The distance matrix is scaled to vary between 0 and 1 under the hood to improve model sampling.
fit <-
coev_fit(
data = authority$data,
variables = list(
political_authority = "ordered_logistic",
religious_authority = "ordered_logistic"
),
id = "language",
tree = authority$phylogeny,
# declare longitude and latitude values
lon_lat = authority$coordinates,
# set manual prior
prior = list(A_offdiag = "normal(0, 2)"),
# additional arguments for cmdstanr
parallel_chains = 4,
iter_sampling = 2000,
iter_warmup = 2000,
refresh = 0,
seed = 1
)Running MCMC with 4 parallel chains...
Chain 4 finished in 663.9 seconds.
Chain 3 finished in 666.8 seconds.
Chain 1 finished in 937.3 seconds.
Chain 2 finished in 948.6 seconds.
All 4 chains finished successfully.
Mean chain execution time: 804.1 seconds.
Total execution time: 948.8 seconds.
Variables: political_authority = ordered_logistic
religious_authority = ordered_logistic
Data: authority$data (Number of observations: 97)
Phylogeny: authority$phylogeny (Number of trees: 1)
Draws: 4 chains, each with iter = 2000; warmup = 2000; thin = 1
total post-warmup draws = 8000
Autoregressive selection effects:
Estimate Est.Error 2.5% 97.5% Rhat Bulk_ESS Tail_ESS
political_authority -0.72 0.55 -2.05 -0.02 1.00 5213 3202
religious_authority -0.74 0.57 -2.11 -0.03 1.00 5142 3170
Cross selection effects:
Estimate Est.Error 2.5% 97.5% Rhat Bulk_ESS Tail_ESS
political_authority ⟶ religious_authority 1.85 1.25 -0.75 4.25 1.00 2799 2793
religious_authority ⟶ political_authority 1.58 1.32 -1.17 4.14 1.00 2792 3400
Drift parameters:
Estimate Est.Error 2.5% 97.5% Rhat Bulk_ESS Tail_ESS
sd(political_authority) 1.25 0.74 0.09 2.79 1.00 1677 3694
sd(religious_authority) 0.96 0.66 0.04 2.43 1.00 2048 3443
cor(political_authority,religious_authority) 0.12 0.33 -0.54 0.71 1.00 6632 5947
Continuous time intercept parameters:
Estimate Est.Error 2.5% 97.5% Rhat Bulk_ESS Tail_ESS
political_authority 0.38 0.96 -1.50 2.28 1.00 9242 5774
religious_authority 0.38 0.97 -1.50 2.26 1.00 9177 5522
Ordinal cutpoint parameters:
Estimate Est.Error 2.5% 97.5% Rhat Bulk_ESS Tail_ESS
political_authority[1] -1.56 1.03 -3.58 0.50 1.00 6188 5898
political_authority[2] -0.83 1.02 -2.81 1.20 1.00 5682 6007
political_authority[3] 1.31 1.06 -0.72 3.44 1.00 4159 5082
religious_authority[1] -1.90 1.05 -3.96 0.18 1.00 6116 4866
religious_authority[2] -1.19 1.04 -3.23 0.88 1.00 6325 5471
religious_authority[3] 1.51 1.08 -0.60 3.70 1.00 5441 5222
Gaussian Process parameters for distances:
Estimate Est.Error 2.5% 97.5% Rhat Bulk_ESS Tail_ESS
rho(political_authority) 0.10 0.07 0.04 0.22 1.00 860 1169
rho(religious_authority) 0.07 0.05 0.03 0.18 1.00 782 456
sdgp(political_authority) 1.86 0.76 0.59 3.61 1.00 2300 1541
sdgp(religious_authority) 2.37 0.79 1.04 4.19 1.00 2136 2029
Warning: There were 13 divergent transitions after warmup.
http://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
The summary output shows that the model has estimated the parameters for two Gaussian process functions over geographic locations, one for each variable.
In addition, it is possible to change the underlying covariance
kernel for the Gaussian processes using the dist_cov
argument and estimate approximate Hilbert-space Gaussian processes using
the dist_k argument. The latter may be particularly useful
for large datasets where exact Gaussian processes are intractable. See
help(coev_fit) for more details.