<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Tidy Ecology</title>
<link>https://tidyecology.com/</link>
<atom:link href="https://tidyecology.com/index.xml" rel="self" type="application/rss+xml"/>
<description>Reproducible R and QGIS workflows for ecologists and conservation biologists.</description>
<image>
<url>https://tidyecology.com/og-image.png</url>
<title>Tidy Ecology</title>
<link>https://tidyecology.com/</link>
<height>76</height>
<width>144</width>
</image>
<generator>quarto-1.9.38</generator>
<lastBuildDate>Sat, 20 Jun 2026 07:00:00 GMT</lastBuildDate>
<item>
  <title>Constrained ordination with distance-based RDA in R</title>
  <dc:creator>Tidy Ecology</dc:creator>
  <link>https://tidyecology.com/posts/constrained-ordination-dbrda/</link>
  <description><![CDATA[ 





<p>The <a href="../../posts/nmds-ordination/index.html">ordination</a> and <a href="../../posts/envfit-and-permanova/index.html">hypothesis-testing</a> posts shared a shape: build an unconstrained map of composition, then bring the environment to it, either as <code>envfit()</code> arrows or as an <code>adonis2()</code> test. Constrained ordination turns that around. Instead of arranging sites by whatever varies most and checking the environment afterward, it builds the axes out of the predictors themselves, so the picture shows only the variation those predictors can account for. Distance-based RDA, <code>dbrda()</code>, is the version that works from a dissimilarity such as Bray-Curtis, which makes it the natural constrained partner to everything in the previous two posts.</p>
<section id="a-dataset-with-two-gradients" class="level2">
<h2 class="anchored" data-anchor-id="a-dataset-with-two-gradients">A dataset with two gradients</h2>
<p>The data is synthetic so the structure is known. Forty sites carry two measured variables, soil moisture and soil nitrogen, drawn independently of each other. Fourteen species each respond to both, peaking at their own point along moisture and at a separate point along nitrogen. Because the two gradients are independent by construction, a good method should pull them apart and credit each with its own share of the pattern.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(vegan)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb2-2">n <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span></span>
<span id="cb2-3">moisture <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-4">nitrogen <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-5"></span>
<span id="cb2-6">species <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sp%02d"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>)</span>
<span id="cb2-7">opt_m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>)            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># moisture optimum per species</span></span>
<span id="cb2-8">opt_n <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>))    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># nitrogen optimum, independent of moisture</span></span>
<span id="cb2-9">w <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.3</span></span>
<span id="cb2-10">lambda <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(species), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i)</span>
<span id="cb2-11">  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>((moisture <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> opt_m[i])<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (nitrogen <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> opt_n[i])<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> w<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)))</span>
<span id="cb2-12">comm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rpois</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(lambda), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(lambda)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n)</span>
<span id="cb2-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(comm) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> species</span>
<span id="cb2-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(comm) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"S%02d"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n)</span>
<span id="cb2-15"></span>
<span id="cb2-16">env <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">moisture =</span> moisture, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nitrogen =</span> nitrogen)</span>
<span id="cb2-17">comm[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>    sp01 sp02 sp03 sp04 sp05 sp06 sp07
S01    0    0    1    0    0    0    1
S02    0    0    0    3    0    0    0
S03    7    1   12    6    7    8    3
S04    0    1   11    0    5    7    2
S05    0    0    0    0    2    1    2</code></pre>
</div>
</div>
</section>
<section id="building-the-model" class="level2">
<h2 class="anchored" data-anchor-id="building-the-model">Building the model</h2>
<p><code>dbrda()</code> takes a formula with the community on the left and the predictors on the right, plus the dissimilarity to use. It computes the Bray-Curtis distances, then finds the axes through that distance space that the predictors can explain, leaving the rest as unconstrained residual structure.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">mod <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dbrda</span>(comm <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> moisture <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> nitrogen, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> env, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">distance =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bray"</span>)</span>
<span id="cb4-2">mod</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Call: dbrda(formula = comm ~ moisture + nitrogen, data = env, distance =
"bray")

              Inertia Proportion Rank RealDims
Total          9.8765     1.0000              
Constrained    5.5768     0.5647    2        2
Unconstrained  4.2997     0.4353   37       21

Inertia is squared Bray distance

Eigenvalues for constrained axes:
dbRDA1 dbRDA2 
3.1394 2.4374 

Eigenvalues for unconstrained axes:
  MDS1   MDS2   MDS3   MDS4   MDS5   MDS6   MDS7   MDS8 
1.6793 0.5864 0.5176 0.4716 0.2922 0.2687 0.2427 0.2012 
(Showing 8 of 37 unconstrained eigenvalues)</code></pre>
</div>
</div>
<p>The summary splits the total inertia into a constrained part and an unconstrained part. The constrained rows are the variation that moisture and nitrogen jointly account for; the unconstrained rows are what is left. Here the two predictors carry a little over half of the total, and the constrained side has exactly two axes, one per predictor, named <code>dbRDA1</code> and <code>dbRDA2</code>.</p>
</section>
<section id="how-much-is-explained" class="level2">
<h2 class="anchored" data-anchor-id="how-much-is-explained">How much is explained</h2>
<p>The constrained proportion is the headline number, but raw proportions climb whenever you add predictors, whether or not they matter. <code>RsquareAdj()</code> corrects for that, the same way adjusted R-squared does in a linear model, and the adjusted figure is the one to quote.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">RsquareAdj</span>(mod)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>$r.squared
[1] 0.564657

$adj.r.squared
[1] 0.5411249</code></pre>
</div>
</div>
<p>About 56 percent of the compositional variation is constrained, and the adjusted value stays close to it (near 0.54), because two predictors against forty sites is not a demanding ratio.</p>
</section>
<section id="is-the-model-significant" class="level2">
<h2 class="anchored" data-anchor-id="is-the-model-significant">Is the model significant?</h2>
<p>The proportion tells you the size of the effect; permutation tests tell you whether it beats chance. <code>anova()</code> on a <code>dbrda</code> object reshuffles the data many times and compares. Run it three ways: the whole model, then each term, then each axis.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">anova</span>(mod, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">permutations =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">999</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Permutation test for dbrda under reduced model
Permutation: free
Number of permutations: 999

Model: dbrda(formula = comm ~ moisture + nitrogen, data = env, distance = "bray")
         Df SumOfSqs      F Pr(&gt;F)    
Model     2   5.5768 23.995  0.001 ***
Residual 37   4.2997                  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1</code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">anova</span>(mod, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"terms"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">permutations =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">999</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Permutation test for dbrda under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

Model: dbrda(formula = comm ~ moisture + nitrogen, data = env, distance = "bray")
         Df SumOfSqs      F Pr(&gt;F)    
moisture  1   3.1164 26.818  0.001 ***
nitrogen  1   2.4604 21.172  0.001 ***
Residual 37   4.2997                  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1</code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb12-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">anova</span>(mod, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"axis"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">permutations =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">999</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Permutation test for dbrda under reduced model
Forward tests for axes
Permutation: free
Number of permutations: 999

Model: dbrda(formula = comm ~ moisture + nitrogen, data = env, distance = "bray")
         Df SumOfSqs      F Pr(&gt;F)    
dbRDA1    1   3.1394 27.015  0.001 ***
dbRDA2    1   2.4374 21.542  0.001 ***
Residual 37   4.2997                  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1</code></pre>
</div>
</div>
<p>The whole model is significant (pseudo-F around 24, p = 0.001). Split by term, moisture and nitrogen are each highly significant on their own, with similar F values, which fits the way they were built as two real and independent drivers. Split by axis, both constrained axes carry signal worth keeping, so a two-dimensional plot is justified rather than just convenient.</p>
</section>
<section id="the-biplot" class="level2">
<h2 class="anchored" data-anchor-id="the-biplot">The biplot</h2>
<p>A constrained ordination is read as a biplot: site points placed on the constrained axes, and the predictors drawn as arrows pointing in the direction each one increases. Colouring the points by moisture and sizing them by nitrogen lets you check the arrows against the raw values.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">scl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb14-2">site_sc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scores</span>(mod, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">display =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sites"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> scl, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">choices =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb14-3">bp      <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scores</span>(mod, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">display =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bp"</span>,    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scaling =</span> scl, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">choices =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb14-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(site_sc) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AX1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AX2"</span>)</span>
<span id="cb14-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(bp)      <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AX1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AX2"</span>)</span>
<span id="cb14-6">site_sc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>moisture <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> moisture</span>
<span id="cb14-7">site_sc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>nitrogen <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> nitrogen</span>
<span id="cb14-8"></span>
<span id="cb14-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># scale the predictor arrows to sit over the site cloud</span></span>
<span id="cb14-10">mul <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(site_sc[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(bp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)))</span>
<span id="cb14-11">bp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lab <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(bp)</span>
<span id="cb14-12">bp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> bp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>AX1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mul</span>
<span id="cb14-13">bp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> bp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>AX2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mul</span>
<span id="cb14-14"></span>
<span id="cb14-15">eig <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> mod<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>CCA<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>eig</span>
<span id="cb14-16">lab1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dbRDA1 (%.0f%% of fitted)"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> eig[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(eig))</span>
<span id="cb14-17">lab2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dbRDA2 (%.0f%% of fitted)"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> eig[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(eig))</span>
<span id="cb14-18"></span>
<span id="cb14-19"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(site_sc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(AX1, AX2)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#e2e1d4"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_vline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#e2e1d4"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> moisture, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> nitrogen)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_segment</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> bp, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xend =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yend =</span> y), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inherit.aes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb14-24">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">arrow =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrow</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unit</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cm"</span>)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#16241d"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-25">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> bp, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> lab), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">inherit.aes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb14-26">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#16241d"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fontface =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">vjust =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-27">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_gradient</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">low =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#c9b458"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">high =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1d5b4e"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Moisture"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-28">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_size_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">range =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nitrogen"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-29">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> lab1, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> lab2) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-30">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_equal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-dbrda" class="quarto-float quarto-figure quarto-figure-center anchored" alt="A distance-based RDA ordination of forty sites on two axes. Site points are coloured from gold for dry to dark green for wet, and sized by nitrogen. Two arrows start from the centre: one labelled moisture points left toward the wet sites, the other labelled nitrogen points downward, and the two arrows are close to perpendicular.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-dbrda-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/constrained-ordination-dbrda/index_files/figure-html/fig-dbrda-1.png" class="img-fluid figure-img" alt="A distance-based RDA ordination of forty sites on two axes. Site points are coloured from gold for dry to dark green for wet, and sized by nitrogen. Two arrows start from the centre: one labelled moisture points left toward the wet sites, the other labelled nitrogen points downward, and the two arrows are close to perpendicular." width="748">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-dbrda-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Distance-based RDA biplot. Sites are coloured by moisture and sized by nitrogen; arrows show the two predictors. The first axis tracks moisture, the second nitrogen, and the arrows sit at almost a right angle because the gradients are independent.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The first axis lines up with moisture: dry gold sites on one side, wet green ones on the other. The second axis lines up with nitrogen, and the point sizes grow along it. The two arrows meet at close to a right angle, the visual signature of predictors that vary independently. If moisture and nitrogen had been correlated in the field, the arrows would have drawn together, and the constrained axes would have struggled to separate their effects.</p>
</section>
<section id="how-this-differs-from-nmds-and-permanova" class="level2">
<h2 class="anchored" data-anchor-id="how-this-differs-from-nmds-and-permanova">How this differs from NMDS and PERMANOVA</h2>
<p>The three approaches answer different questions about the same kind of data. NMDS is unconstrained: it shows the full compositional structure and asks nothing of the environment until you overlay it with <code>envfit()</code>, which makes it the tool for exploring what is there. PERMANOVA tests whether named predictors explain composition but returns no map. Distance-based RDA does both at once: the <code>anova()</code> output is the test, and the biplot is the picture, but the picture shows only the slice of variation the predictors govern, not everything in the data. Reach for NMDS when you want to see all the structure and form hypotheses, and for <code>dbrda()</code> when you already have the predictors and want to model, measure, and display their effect directly.</p>
</section>
<section id="where-to-go-next" class="level2">
<h2 class="anchored" data-anchor-id="where-to-go-next">Where to go next</h2>
<p><code>capscale()</code> is the close sibling of <code>dbrda()</code>, also distance-based, differing mainly in how each treats the negative eigenvalues that non-Euclidean distances can produce. A <code>Condition()</code> term partials out covariates you want to control for rather than test, and <code>varpart()</code> splits the explained variation among several predictor sets to show how much each contributes alone and how much they share. All of them build on the same move made here: let the predictors define the ordination, then test what they are worth.</p>


<!-- -->

</section>

 ]]></description>
  <category>R</category>
  <category>vegan</category>
  <category>ordination</category>
  <category>constrained ordination</category>
  <category>community ecology</category>
  <guid>https://tidyecology.com/posts/constrained-ordination-dbrda/</guid>
  <pubDate>Sat, 20 Jun 2026 07:00:00 GMT</pubDate>
  <media:content url="https://tidyecology.com/posts/constrained-ordination-dbrda/thumbnail.png" medium="image" type="image/png" height="117" width="144"/>
</item>
<item>
  <title>Mapping species richness in R with sf</title>
  <dc:creator>Tidy Ecology</dc:creator>
  <link>https://tidyecology.com/posts/richness-mapping-sf/</link>
  <description><![CDATA[ 





<p>The posts so far have treated a survey as a table: rows are sites, columns are species. Field data usually carries one more thing, which is where each record sat on the ground. Once coordinates are in play, a different question opens up. Not how many species there are overall, but where the richness is concentrated. This post takes a set of occurrence records, builds a grid, counts species per cell, and draws the map, all in R with the <code>sf</code> package. It ends by writing a GeoPackage, which is the clean handoff to QGIS for anyone who wants to finish the cartography there.</p>
<section id="occurrence-records" class="level2">
<h2 class="anchored" data-anchor-id="occurrence-records">Occurrence records</h2>
<p>The data is synthetic so the pattern is known up front. It holds occurrence records for twelve species across a study region, each record a species name and a longitude and latitude. Two gradients are built in. One runs east to west and decides which species occur where, so composition turns over across the region. The other runs south to north and sets how many species a place can support, standing in for something like productivity. The result should be a richness map that rises toward the north and thins at the dry and wet edges of the compositional gradient.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(sf)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>)</span>
<span id="cb2-2">lon_range <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">23.40</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">23.72</span>)</span>
<span id="cb2-3">lat_range <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">46.62</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">46.90</span>)</span>
<span id="cb2-4"></span>
<span id="cb2-5">n_pts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">900</span></span>
<span id="cb2-6">pool <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lon =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n_pts, lon_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], lon_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]),</span>
<span id="cb2-7">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lat =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n_pts, lat_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], lat_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]))</span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># east-west gradient drives which species occur; south-north drives how many</span></span>
<span id="cb2-10">pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>env  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lon <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> lon_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diff</span>(lon_range)</span>
<span id="cb2-11">pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>prod <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> lat_range[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diff</span>(lat_range)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 0 south .. 1 north</span></span>
<span id="cb2-12"></span>
<span id="cb2-13">species <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sp%02d"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span>
<span id="cb2-14">opt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(species))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># each species peaks at its own point</span></span>
<span id="cb2-15">w   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.6</span></span>
<span id="cb2-16">occ <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(rbind, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(species), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i) {</span>
<span id="cb2-17">  prob <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>prod) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>((pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>env <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> opt[i])<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> w<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb2-18">  hit  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n_pts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> prob</span>
<span id="cb2-19">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(hit)) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>)</span>
<span id="cb2-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">species =</span> species[i], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lon =</span> pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lon[hit], <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lat =</span> pool<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lat[hit])</span>
<span id="cb2-21">}))</span>
<span id="cb2-22"></span>
<span id="cb2-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(occ)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 2325</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(occ)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>  species      lon      lat
1    sp01 23.43702 46.89398
2    sp01 23.47800 46.68298
3    sp01 23.45307 46.86184
4    sp01 23.43082 46.79905
5    sp01 23.42710 46.88506
6    sp01 23.40279 46.65932</code></pre>
</div>
</div>
</section>
<section id="from-a-data-frame-to-spatial-points" class="level2">
<h2 class="anchored" data-anchor-id="from-a-data-frame-to-spatial-points">From a data frame to spatial points</h2>
<p>Right now <code>occ</code> is an ordinary data frame with two columns that happen to hold coordinates. <code>st_as_sf()</code> turns it into a spatial object by naming those columns and stating their coordinate reference system. The records are longitude and latitude in degrees, which is the system EPSG code 4326, also called WGS84.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">pts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_as_sf</span>(occ, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">coords =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lon"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lat"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">crs =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4326</span>)</span>
<span id="cb6-2">pts</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Simple feature collection with 2325 features and 1 field
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 23.40047 ymin: 46.62073 xmax: 23.71754 ymax: 46.89957
Geodetic CRS:  WGS 84
First 10 features:
   species                  geometry
1     sp01 POINT (23.43702 46.89398)
2     sp01   POINT (23.478 46.68298)
3     sp01 POINT (23.45307 46.86184)
4     sp01 POINT (23.43082 46.79905)
5     sp01  POINT (23.4271 46.88506)
6     sp01 POINT (23.40279 46.65932)
7     sp01 POINT (23.50131 46.83239)
8     sp01 POINT (23.45943 46.69458)
9     sp01 POINT (23.50225 46.74057)
10    sp01 POINT (23.45209 46.73221)</code></pre>
</div>
</div>
<p>The print now shows a geometry column and a header describing the CRS and the bounding box. Each row is still one occurrence, but the position is a real point that <code>sf</code> can measure and join against.</p>
</section>
<section id="projecting-before-measuring" class="level2">
<h2 class="anchored" data-anchor-id="projecting-before-measuring">Projecting before measuring</h2>
<p>Degrees are fine for storing where something is, but poor for measuring. A degree of longitude covers a different ground distance at the equator than near the poles, so a grid built in degrees would have cells of unequal area. The fix is to project the points onto a flat system whose units are metres. This region sits in UTM zone 34 north, EPSG code 32634, so a grid built there is honest about distance.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">pts_utm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_transform</span>(pts, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32634</span>)</span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_crs</span>(pts_utm)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>epsg</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 32634</code></pre>
</div>
</div>
</section>
<section id="a-grid-and-species-per-cell" class="level2">
<h2 class="anchored" data-anchor-id="a-grid-and-species-per-cell">A grid, and species per cell</h2>
<p><code>st_make_grid()</code> lays a regular net over the extent of the points. A two kilometre cell is a reasonable resolution for this region. Wrapping the result with <code>st_sf()</code> and a <code>cell_id</code> makes it a proper layer that can carry attributes.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_make_grid</span>(pts_utm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cellsize =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2000</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">square =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb10-2">grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_sf</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cell_id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(grid), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">geometry =</span> grid)</span>
<span id="cb10-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(grid)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 208</code></pre>
</div>
</div>
<p><code>st_join()</code> attaches to every point the cell it falls in (the default test is <code>st_intersects</code>). After that, richness per cell is a plain grouped count of distinct species. Cells that caught no records drop out, so the map shows only the surveyed area.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">grid_rich <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_join</span>(pts_utm, grid) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb12-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_drop_geometry</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb12-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(cell_id) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb12-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">richness =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n_distinct</span>(species), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_records =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>(), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.groups =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"drop"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb12-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">right_join</span>(grid, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_id"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb12-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_as_sf</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb12-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(richness))</span>
<span id="cb12-8"></span>
<span id="cb12-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">range</span>(grid_rich<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>richness)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1]  1 11</code></pre>
</div>
</div>
</section>
<section id="the-map" class="level2">
<h2 class="anchored" data-anchor-id="the-map">The map</h2>
<p><code>geom_sf()</code> reads the geometry directly, so the grid and the points need no x and y aesthetics. Filling the cells by richness and dropping the raw points on top shows both the pattern and the sampling behind it.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_sf</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> grid_rich, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> richness), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_sf</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> pts_utm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#16241d"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.22</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_gradient</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">low =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#f5f4ee"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">high =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#275139"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Species</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">richness"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-richness" class="quarto-float quarto-figure quarto-figure-center anchored" alt="A map of the study region divided into square grid cells shaded from pale to dark green by species richness. Darker, more species-rich cells cluster toward the north and the centre, while the southern edge and the far east and west are paler. Small dark dots mark the individual occurrence records.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-richness-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/richness-mapping-sf/index_files/figure-html/fig-richness-1.png" class="img-fluid figure-img" alt="A map of the study region divided into square grid cells shaded from pale to dark green by species richness. Darker, more species-rich cells cluster toward the north and the centre, while the southern edge and the far east and west are paler. Small dark dots mark the individual occurrence records." width="691">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-richness-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Species richness per two kilometre cell, with occurrence records overlaid. Richness rises toward the north and peaks near the middle of the east-west gradient.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The map reads the way the data was built. The north holds the richest cells, the south is thinner, and within any band the middle of the region carries more species than the far east or west, because the edge species of the compositional gradient drop out there. The graticule still shows degrees even though the data is now in metres, because <code>geom_sf()</code> reprojects the grid lines for display.</p>
</section>
<section id="handing-off-to-qgis" class="level2">
<h2 class="anchored" data-anchor-id="handing-off-to-qgis">Handing off to QGIS</h2>
<p>R is good at the analysis; QGIS is often where the final cartography happens. A GeoPackage moves the result across cleanly. It is a single open file that QGIS opens natively, and <code>st_write()</code> produces it. The same call works for the points, so both layers travel together.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_write</span>(grid_rich, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"richness_grid.gpkg"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">delete_dsn =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb15-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_write</span>(pts_utm,   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"occurrences.gpkg"</span>,   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">delete_dsn =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
</div>
<p>Open <code>richness_grid.gpkg</code> in QGIS and the cells arrive with the <code>richness</code> field ready to style, project, and lay out as a finished figure.</p>
</section>
<section id="where-to-go-next" class="level2">
<h2 class="anchored" data-anchor-id="where-to-go-next">Where to go next</h2>
<p><code>sf</code> is the backbone for vector work in R: points, lines, and polygons, with joins, buffers, and distance calculations on top. From here, the same grid can be joined to polygons such as protected areas or administrative units to summarise richness within them, <code>st_buffer()</code> and <code>st_distance()</code> answer proximity questions, and the <code>terra</code> package covers the raster side when the environment comes as continuous surfaces rather than points. With the GeoPackage written, the rest of the map can move to QGIS whenever that is the better tool for the layout.</p>


<!-- -->

</section>

 ]]></description>
  <category>R</category>
  <category>sf</category>
  <category>spatial</category>
  <category>GIS</category>
  <category>mapping</category>
  <guid>https://tidyecology.com/posts/richness-mapping-sf/</guid>
  <pubDate>Sat, 20 Jun 2026 06:00:00 GMT</pubDate>
  <media:content url="https://tidyecology.com/posts/richness-mapping-sf/thumbnail.png" medium="image" type="image/png" height="117" width="144"/>
</item>
<item>
  <title>Putting statistics on an ordination: envfit and PERMANOVA</title>
  <dc:creator>Tidy Ecology</dc:creator>
  <link>https://tidyecology.com/posts/envfit-and-permanova/</link>
  <description><![CDATA[ 





<p><a href="../../posts/nmds-ordination/index.html">The ordination post</a> built an NMDS and even confirmed that its first axis recovered a known moisture gradient. A map is a good start, but it leaves two questions open. Which of the variables you measured in the field actually line up with the pattern? And when sites fall into groups, such as different management regimes, do those groups really differ in composition, or do they only look separated because the eye is generous? <code>envfit()</code> answers the first question and <code>adonis2()</code> answers the second. A third function, <code>betadisper()</code>, stops the second answer from fooling you.</p>
<section id="a-grassland-survey" class="level2">
<h2 class="anchored" data-anchor-id="a-grassland-survey">A grassland survey</h2>
<p>The dataset is a constructed one again, so that we know the right answer in advance. Thirty grassland plots fall into three management regimes, ten plots each: grazed, mown, and abandoned. For every plot we have soil moisture, soil pH, and counts for fourteen plant species. Moisture drives a turnover of specialists from dry to wet ground. Management acts on top of that: grazing favours low ruderal species and suppresses tall ones, abandonment does the reverse, and mowing sits in between. Soil pH was measured too, but it was scattered at random across the plots, so it should turn out to explain nothing. That last point matters, because a method worth using has to be able to return a clear negative.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(vegan)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb2-2"></span>
<span id="cb2-3">n_per <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb2-4">mgmt  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Grazed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mown"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Abandoned"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> n_per),</span>
<span id="cb2-5">                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Grazed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mown"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Abandoned"</span>))</span>
<span id="cb2-6">n <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(mgmt)</span>
<span id="cb2-7"></span>
<span id="cb2-8">moisture <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># structuring gradient</span></span>
<span id="cb2-9">pH       <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(n, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">7.3</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># measured, but random by design</span></span>
<span id="cb2-10"></span>
<span id="cb2-11">species <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Thymus"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sedum"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Festuca"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Briza"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Trifolium"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Plantago"</span>,</span>
<span id="cb2-12">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lotus"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Filipendula"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Juncus"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Carex"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Taraxacum"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poa"</span>,</span>
<span id="cb2-13">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Achillea"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Urtica"</span>)</span>
<span id="cb2-14">peaks <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">9.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(species))</span>
<span id="cb2-15">base  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(moisture, peaks, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m, p) <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>((m <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.8</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)))</span>
<span id="cb2-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(base) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> species</span>
<span id="cb2-17"></span>
<span id="cb2-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># management shifts the balance of ruderal and tall competitor species</span></span>
<span id="cb2-19">ruderal    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Taraxacum"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poa"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Trifolium"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Plantago"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lotus"</span>)</span>
<span id="cb2-20">competitor <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Filipendula"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Urtica"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Carex"</span>)</span>
<span id="cb2-21">mult <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, n, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(species), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dimnames =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, species))</span>
<span id="cb2-22">mult[mgmt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Grazed"</span>,    ruderal]    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.4</span></span>
<span id="cb2-23">mult[mgmt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Grazed"</span>,    competitor] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.35</span></span>
<span id="cb2-24">mult[mgmt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Abandoned"</span>, ruderal]    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span></span>
<span id="cb2-25">mult[mgmt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Abandoned"</span>, competitor] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.4</span></span>
<span id="cb2-26"></span>
<span id="cb2-27">comm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rpois</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(base <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mult), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(base <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mult)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n)</span>
<span id="cb2-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(comm) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> species</span>
<span id="cb2-29"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(comm) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"S%02d"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n)</span>
<span id="cb2-30"></span>
<span id="cb2-31">env <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">moisture =</span> moisture, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pH =</span> pH, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mgmt =</span> mgmt)</span>
<span id="cb2-32"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(mgmt)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>mgmt
   Grazed      Mown Abandoned 
       10        10        10 </code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">comm[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>    Thymus Sedum Festuca Briza Trifolium Plantago Lotus
S01      0     0       0     0         1        2     5
S02      0     0       0     0         1        1     1
S03      3     2       6     9        17       16    11
S04      0     0       0     0         2        5     1
S05      0     1       1     2         9        9    17</code></pre>
</div>
</div>
</section>
<section id="the-ordination-briefly" class="level2">
<h2 class="anchored" data-anchor-id="the-ordination-briefly">The ordination, briefly</h2>
<p>The ordination itself is the same recipe as last time: Bray-Curtis dissimilarities, then <code>metaMDS()</code>. The earlier post covers what the arguments mean and how to read the stress.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb6-2">ord <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metaMDS</span>(comm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">distance =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bray"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">k =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trymax =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb6-3">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">autotransform =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb6-4">ord<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>stress</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.0715636</code></pre>
</div>
</div>
<p>A stress around 0.07 is a good fit, so the map is worth interpreting. Everything below works from this <code>ord</code> object and the matching <code>env</code> table.</p>
</section>
<section id="envfit-which-variables-line-up-with-the-map" class="level2">
<h2 class="anchored" data-anchor-id="envfit-which-variables-line-up-with-the-map">envfit: which variables line up with the map?</h2>
<p><code>envfit()</code> takes the ordination and a table of environmental variables and asks, for each variable, how well it aligns with the arrangement of sites. A continuous variable is fitted as a vector: the direction across the plot along which it increases fastest, with an r-squared for how tightly the sites follow that direction and a permutation p-value for whether the alignment beats chance. A factor is fitted as a set of centroids, one mean position per group, with its own r-squared and test.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb8-2">fit <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">envfit</span>(ord, env, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">permutations =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">999</span>)</span>
<span id="cb8-3">fit</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
***VECTORS

            NMDS1    NMDS2     r2 Pr(&gt;r)    
moisture -0.97781 -0.20950 0.9756  0.001 ***
pH       -0.55593 -0.83123 0.0361  0.624    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Permutation: free
Number of permutations: 999

***FACTORS:

Centroids:
                NMDS1   NMDS2
mgmtGrazed     0.0525 -0.5261
mgmtMown       0.0208  0.0242
mgmtAbandoned -0.0733  0.5019

Goodness of fit:
         r2 Pr(&gt;r)  
mgmt 0.2189  0.017 *
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Permutation: free
Number of permutations: 999</code></pre>
</div>
</div>
<p>The reading is clean. Moisture aligns almost perfectly with the ordination (r-squared near 0.98) and is highly significant. Management separates its three centroids and is significant as well, though it accounts for less. Soil pH, exactly as built, lands near zero and is not significant, so we have our negative control back. On the plot we draw only the vector that earned its place.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">mgmt_cols <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Grazed =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#cda23f"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Mown =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f8f63"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Abandoned =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b5534e"</span>)</span>
<span id="cb10-2">site_sc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scores</span>(ord, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sites"</span>))</span>
<span id="cb10-3">site_sc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mgmt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> mgmt</span>
<span id="cb10-4"></span>
<span id="cb10-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># scale the significant vector by hand so its length reflects strength</span></span>
<span id="cb10-6">arr    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scores</span>(fit, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vectors"</span>)</span>
<span id="cb10-7">radius <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(site_sc[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])))</span>
<span id="cb10-8">mul    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.78</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> radius <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(arr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)))</span>
<span id="cb10-9">moist  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(arr[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"moisture"</span>, , <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">drop =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mul)</span>
<span id="cb10-10"></span>
<span id="cb10-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(site_sc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(NMDS1, NMDS2)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#e2e1d4"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_vline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#e2e1d4"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stat_ellipse</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> mgmt), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">level =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> mgmt, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> mgmt), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stroke =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_segment</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> moist, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xend =</span> NMDS1, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yend =</span> NMDS2),</span>
<span id="cb10-17">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">arrow =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrow</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unit</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.18</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cm"</span>)),</span>
<span id="cb10-18">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#16241d"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">annotate</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> moist<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>NMDS1 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> moist<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>NMDS2 <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.05</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.07</span>,</span>
<span id="cb10-20">           <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"moisture"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#16241d"</span>,</span>
<span id="cb10-21">           <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fontface =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"italic"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> mgmt_cols, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Management"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> mgmt_cols, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Management"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-24">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_equal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.8</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ylim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-25">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-biplot" class="quarto-float quarto-figure quarto-figure-center anchored" alt="NMDS scatter plot of thirty plots coloured by management regime, grazed in gold, mown in green, abandoned in red, each wrapped in a confidence ellipse. The three ellipses are stacked vertically along the second axis, showing that management separates the groups in that direction, while a single arrow labelled moisture points along the first axis.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-biplot-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/envfit-and-permanova/index_files/figure-html/fig-biplot-1.png" class="img-fluid figure-img" alt="NMDS scatter plot of thirty plots coloured by management regime, grazed in gold, mown in green, abandoned in red, each wrapped in a confidence ellipse. The three ellipses are stacked vertically along the second axis, showing that management separates the groups in that direction, while a single arrow labelled moisture points along the first axis." width="748">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-biplot-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Sites in NMDS space, grouped by management (95% confidence ellipses), with the significant moisture vector. pH was fitted but was not significant (r-squared about 0.04, p about 0.62) and is not drawn.
</figcaption>
</figure>
</div>
</div>
</div>
<p>Two things are worth keeping in mind about envfit. A vector arrow assumes the variable changes smoothly and roughly linearly across the ordination plane. When a variable instead peaks in the middle and falls off at both ends, a straight arrow misrepresents it, and <code>ordisurf()</code> is the better tool: it drapes a fitted smooth surface over the ordination instead of a single direction. And a significant envfit result describes alignment with an existing picture, not a formal model of composition. For the latter, the next function is the one you want.</p>
</section>
<section id="permanova-with-adonis2-do-the-groups-really-differ" class="level2">
<h2 class="anchored" data-anchor-id="permanova-with-adonis2-do-the-groups-really-differ">PERMANOVA with adonis2: do the groups really differ?</h2>
<p>Seeing three ellipses stack up is suggestive, but eyes find groups in noise. <code>adonis2()</code> runs PERMANOVA, which partitions the dissimilarity matrix among the predictors and asks, by reshuffling group labels many times, whether each predictor explains more of the total composition than random labelling would.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb11-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">adonis2</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vegdist</span>(comm, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bray"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> mgmt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> moisture <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pH,</span>
<span id="cb11-3">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> env, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">permutations =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">999</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"terms"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = vegdist(comm, "bray") ~ mgmt + moisture + pH, data = env, permutations = 999, by = "terms")
         Df SumOfSqs      R2       F Pr(&gt;F)    
mgmt      2   1.4106 0.22436  9.0308  0.001 ***
moisture  1   2.8622 0.45524 36.6484  0.001 ***
pH        1   0.0620 0.00986  0.7940  0.501    
Residual 25   1.9525 0.31054                   
Total    29   6.2874 1.00000                   
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1</code></pre>
</div>
</div>
<p>Each row carries a pseudo-F, an R-squared, and a permutation p-value. The R-squared is the share of the total multivariate variation that the term accounts for. Moisture takes the largest share, management a solid further chunk, and pH almost nothing, with a p-value that confirms it. The residual line is the variation left unexplained.</p>
<p>One detail decides how you read the table. <code>by = "terms"</code> adds the predictors in order, so each is tested on what is left after the ones above it. <code>by = "margin"</code> instead tests each predictor with all the others already accounted for. When predictors are independent, as moisture and management are here by construction, the two versions agree closely. When predictors are correlated, they can disagree sharply, and the order you wrote the formula in starts to change the story. Reaching for <code>by = "margin"</code> is the safer habit whenever you are unsure.</p>
</section>
<section id="betadisper-is-the-difference-real-or-just-uneven-spread" class="level2">
<h2 class="anchored" data-anchor-id="betadisper-is-the-difference-real-or-just-uneven-spread">betadisper: is the difference real, or just uneven spread?</h2>
<p>PERMANOVA has a trap that catches a lot of published work. It can return a significant result not because the group centroids sit in different places, but because the groups differ in how spread out they are internally. A tight cluster and a diffuse cloud can test as significantly different even with the same centre. <code>betadisper()</code> measures each plot’s distance to its own group centroid and tests whether that spread differs between groups.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1">bd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">betadisper</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vegdist</span>(comm, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bray"</span>), mgmt)</span>
<span id="cb13-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb13-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">permutest</span>(bd, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">permutations =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">999</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 999

Response: Distances
          Df  Sum Sq  Mean Sq      F N.Perm Pr(&gt;F)
Groups     2 0.05701 0.028504 0.9162    999  0.401
Residuals 27 0.84001 0.031112                     </code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mgmt =</span> mgmt, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dist =</span> bd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>distances) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(mgmt, dist, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> mgmt)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_boxplot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.55</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outlier.shape =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.85</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.12</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2c3a31"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> mgmt_cols, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">guide =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Distance to group centroid"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-betadisper" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Box plot of the distance from each plot to its management group centroid, for grazed, mown, and abandoned plots. The three distributions overlap heavily, with similar medians and ranges, indicating comparable within-group spread.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-betadisper-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/envfit-and-permanova/index_files/figure-html/fig-betadisper-1.png" class="img-fluid figure-img" alt="Box plot of the distance from each plot to its management group centroid, for grazed, mown, and abandoned plots. The three distributions overlap heavily, with similar medians and ranges, indicating comparable within-group spread." width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-betadisper-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Distance from each plot to its group centroid. Similar spread across groups means the PERMANOVA result reflects a real shift in composition, not uneven dispersion.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The test comes back non-significant (p around 0.4), and the box plot agrees: the three groups scatter to a similar degree around their centres. That clears the PERMANOVA. The significant management effect is a genuine difference in where the groups sit in composition space, not an artefact of one regime being more variable than another. Had <code>betadisper()</code> been significant, the PERMANOVA p-value would have been unsafe to read as a centroid difference, and you would say so rather than quietly report the F-test. Running the two together, and reporting both, is the honest minimum.</p>
</section>
<section id="where-to-go-next" class="level2">
<h2 class="anchored" data-anchor-id="where-to-go-next">Where to go next</h2>
<p>The three functions form a small workflow: <code>envfit()</code> to see which gradients align with the map, <code>adonis2()</code> to test whether groupings explain composition, and <code>betadisper()</code> to make sure that test means what you think. From here, a pairwise PERMANOVA tells you which specific managements differ rather than just that some do; <code>ordisurf()</code> handles variables whose response curves bend; and constrained methods such as distance-based RDA (<code>capscale()</code> and <code>dbrda()</code>) let you model composition directly against predictors instead of fitting them onto an unconstrained map after the fact.</p>


<!-- -->

</section>

 ]]></description>
  <category>R</category>
  <category>vegan</category>
  <category>ordination</category>
  <category>PERMANOVA</category>
  <category>community ecology</category>
  <guid>https://tidyecology.com/posts/envfit-and-permanova/</guid>
  <pubDate>Sat, 20 Jun 2026 05:00:00 GMT</pubDate>
  <media:content url="https://tidyecology.com/posts/envfit-and-permanova/thumbnail.png" medium="image" type="image/png" height="110" width="144"/>
</item>
<item>
  <title>Ordination with NMDS in R</title>
  <dc:creator>Tidy Ecology</dc:creator>
  <link>https://tidyecology.com/posts/nmds-ordination/</link>
  <description><![CDATA[ 





<p><a href="../../posts/diversity-indices-in-r/index.html">The previous post</a> gave each plot a single diversity number. That answers how <em>much</em> is growing somewhere, but not how two plots resemble each other. Two sites can share an identical Shannon index and have no species in common. To compare what is actually growing where, we need a method that works on composition rather than on totals. Ordination is that method, and non-metric multidimensional scaling (NMDS) is the version most community ecologists reach for first.</p>
<p>This post builds a small dataset whose structure we already know, runs an NMDS with <code>vegan</code>, and then spends most of its time on the parts that decide whether the result is trustworthy: how well the map fits, how many dimensions it needs, and whether the algorithm settled on a stable answer.</p>
<section id="what-ordination-is-for" class="level2">
<h2 class="anchored" data-anchor-id="what-ordination-is-for">What ordination is for</h2>
<p>A community dataset is wide. One row per site, one column per species, counts in the cells. Past three species you can no longer plot the sites directly, because every species is its own axis. Ordination compresses those many axes down to two or three that you can look at, while keeping similar sites close together and different sites far apart. The input is not the raw table but a matrix of pairwise dissimilarities between sites, so the first real decision is how to measure dissimilarity.</p>
</section>
<section id="a-dataset-with-a-known-answer" class="level2">
<h2 class="anchored" data-anchor-id="a-dataset-with-a-known-answer">A dataset with a known answer</h2>
<p>Survey data never arrives with a key, so for learning it helps to build a table whose answer you already know. Below are sixteen sites along a moisture gradient, running from a dry ridge to a wet hollow. Nine specialist species each peak at a different point on that gradient, and three generalists turn up across the whole transect at low numbers. The counts are deliberately small, so every cell carries some sampling noise, the way real plots do.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(vegan)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyr)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-2"></span>
<span id="cb2-3">n_sites  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span></span>
<span id="cb2-4">gradient <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> n_sites)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true moisture, dry to wet</span></span>
<span id="cb2-5"></span>
<span id="cb2-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># nine specialists, each peaking at a different point on the gradient</span></span>
<span id="cb2-7">specialists <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Thymus"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sedum"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Festuca"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Briza"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Trifolium"</span>,</span>
<span id="cb2-8">                 <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Plantago"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Filipendula"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Juncus"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Carex"</span>)</span>
<span id="cb2-9">peaks  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">9.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(specialists))</span>
<span id="cb2-10">lambda <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outer</span>(gradient, peaks, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(g, p) <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>((g <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)))</span>
<span id="cb2-11">spec_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rpois</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(lambda), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.vector</span>(lambda)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_sites)</span>
<span id="cb2-12"></span>
<span id="cb2-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># three generalists present across the whole transect at low numbers</span></span>
<span id="cb2-14">generalists <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rpois</span>(n_sites <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lambda =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_sites)</span>
<span id="cb2-15"></span>
<span id="cb2-16">comm <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(spec_counts, generalists))</span>
<span id="cb2-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(comm) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(specialists, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Taraxacum"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poa"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Achillea"</span>)</span>
<span id="cb2-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(comm) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Site%02d"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_len</span>(n_sites))</span>
<span id="cb2-19"></span>
<span id="cb2-20">comm[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>       Thymus Sedum Festuca Briza Trifolium Plantago Filipendula
Site01      5     5       1     0         0        0           0
Site02      6    12       1     1         0        0           0
Site03      6     6       6     1         0        0           0
Site04      7     9       7     5         2        0           0
Site05      1     9       9     5         0        1           0
Site06      3     2       3     5         6        0           0</code></pre>
</div>
</div>
<p>A picture of the whole table makes the structure obvious.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">sp_levels <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(specialists, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Taraxacum"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poa"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Achillea"</span>)</span>
<span id="cb4-2">long <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> comm <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb4-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Site =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(comm)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb4-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>Site, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Species"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Abundance"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb4-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Species =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(Species, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> sp_levels),</span>
<span id="cb4-6">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Site    =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(Site, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rev</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(comm))))</span>
<span id="cb4-7"></span>
<span id="cb4-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(long, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(Species, Site, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Abundance)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_tile</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_gradient</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">low =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#f5f4ee"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">high =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#275139"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Count"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-matrix" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Heatmap of the sixteen by twelve abundance table. The nine specialist species form a diagonal band of higher counts running from dry sites at the top to wet sites at the bottom, while the three generalist species on the right stay roughly even across all sites.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-matrix-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/nmds-ordination/index_files/figure-html/fig-matrix-1.png" class="img-fluid figure-img" alt="Heatmap of the sixteen by twelve abundance table. The nine specialist species form a diagonal band of higher counts running from dry sites at the top to wet sites at the bottom, while the three generalist species on the right stay roughly even across all sites." width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-matrix-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Abundance of each species across the transect. Specialists form a diagonal band; the three generalists on the right stay roughly even.
</figcaption>
</figure>
</div>
</div>
</div>
<p>Reading down any specialist column, the species rises and falls as you move along the transect; the generalists stay flat. This staircase of overlapping peaks is the signal NMDS has to recover. It also explains why we do not simply run PCA on the raw counts. Species do not track a gradient in straight lines: they appear, peak, and drop out again. A method that assumes linear relationships distorts that badly. NMDS avoids the problem by working only from the rank order of dissimilarities, so the exact shape of each response curve stops mattering.</p>
</section>
<section id="measuring-dissimilarity-first" class="level2">
<h2 class="anchored" data-anchor-id="measuring-dissimilarity-first">Measuring dissimilarity first</h2>
<p><code>vegdist()</code> turns the site-by-species table into pairwise dissimilarities. Bray-Curtis is the usual choice for abundance data. It runs from 0 (identical composition) to 1 (no shared species), and it ignores shared absences, so two sites are not counted as alike merely because the same rare species is missing from both.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">bray <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vegdist</span>(comm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bray"</span>)</span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(bray)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>       Site01 Site02 Site03 Site04 Site05
Site01   0.00   0.23   0.25   0.32   0.50
Site02   0.23   0.00   0.26   0.25   0.36
Site03   0.25   0.26   0.00   0.24   0.29
Site04   0.32   0.25   0.24   0.00   0.23
Site05   0.50   0.36   0.29   0.23   0.00</code></pre>
</div>
</div>
<p>Neighbouring sites sit near zero; sites from opposite ends of the transect climb toward one. That ordering is the only thing NMDS will use.</p>
</section>
<section id="running-the-nmds" class="level2">
<h2 class="anchored" data-anchor-id="running-the-nmds">Running the NMDS</h2>
<p><code>metaMDS()</code> does the work. It computes the dissimilarities, drops the sites onto the plane at random, then shifts them around until the map distances line up with the dissimilarity ranks as closely as possible, repeating the whole thing from many random starts so a single unlucky start cannot decide the outcome.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb7-2">ord <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metaMDS</span>(comm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">distance =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bray"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">k =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trymax =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb7-3">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">autotransform =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb7-4">ord</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Call:
metaMDS(comm = comm, distance = "bray", k = 2, trymax = 100,      autotransform = FALSE, trace = FALSE) 

global Multidimensional Scaling using monoMDS

Data:     comm 
Distance: bray 

Dimensions: 2 
Stress:     0.08219387 
Stress type 1, weak ties
Best solution was repeated 11 times in 20 tries
The best solution was from try 7 (random start)
Scaling: centring, PC rotation, halfchange scaling 
Species: expanded scores based on 'comm' </code></pre>
</div>
</div>
<p>Each argument earns its place. <code>k = 2</code> asks for a two-dimensional map. <code>trymax = 100</code> caps how many random starts are allowed. <code>autotransform = FALSE</code> is worth a note: left on its default, <code>metaMDS()</code> will square-root the counts and apply a standardisation before measuring distance, which is sensible for messy field data but would no longer match the Bray-Curtis matrix we just inspected. Turning it off keeps the steps aligned. <code>set.seed()</code> matters because the starting positions are random, so the run only reproduces if the seed is fixed. <code>trace = FALSE</code> simply silences the per-iteration log.</p>
<p>The printed summary reports the stress (here about 0.08) and a line such as <code>Best solution was repeated 11 times in 20 tries</code>, which says how many of the random starts agreed on the same answer. Those two figures drive the next two sections.</p>
</section>
<section id="stress-does-the-map-fit" class="level2">
<h2 class="anchored" data-anchor-id="stress-does-the-map-fit">Stress: does the map fit?</h2>
<p>Stress measures how much the flat map has to distort the original dissimilarity ranks to fit them into two dimensions. Zero would be a perfect rank match; larger values mean the map is forcing relationships that the data do not support. Clarke’s much-quoted rule of thumb runs roughly: under 0.05 is excellent, under 0.1 is good, under 0.2 is usable but needs a second look, and over 0.3 is barely better than random. A stress near 0.08 sits in the good band, so the picture is worth reading.</p>
<p>To see the fit rather than summarise it, <code>stressplot(ord)</code> draws the Shepard diagram: observed dissimilarities against the map distances, with a step line for the fitted monotonic regression. Points hugging that line are what you want.</p>
</section>
<section id="how-many-dimensions" class="level2">
<h2 class="anchored" data-anchor-id="how-many-dimensions">How many dimensions?</h2>
<p>Two dimensions was a choice, not a rule. One way to test it is to refit the same NMDS across a range of dimensions and watch where the stress stops falling sharply.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">stress_k <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sapply</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) {</span>
<span id="cb9-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metaMDS</span>(comm, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">distance =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bray"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">k =</span> k, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trymax =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb9-4">          <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">autotransform =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>stress</span>
<span id="cb9-5">})</span>
<span id="cb9-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(stress_k, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.177 0.082 0.049 0.027</code></pre>
</div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">k =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stress =</span> stress_k), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(k, stress)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b9534e"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#93a87f"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#275139"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dimensions (k)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Stress"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-stress" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Line chart of NMDS stress against the number of dimensions. Stress falls steeply from about 0.18 at one dimension to about 0.08 at two, then declines only gently at three and four dimensions. A dashed reference line marks a stress of 0.1.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-stress-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/nmds-ordination/index_files/figure-html/fig-stress-1.png" class="img-fluid figure-img" alt="Line chart of NMDS stress against the number of dimensions. Stress falls steeply from about 0.18 at one dimension to about 0.08 at two, then declines only gently at three and four dimensions. A dashed reference line marks a stress of 0.1." width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-stress-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Stress against the number of dimensions. The steep drop ends after two dimensions.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The big improvement from one dimension to two tells us a single axis is too cramped for this data. The small gains after two tell us that further dimensions would mostly be fitting noise. Two is also the number you can actually plot, which is why it is so often where people stop.</p>
</section>
<section id="convergence-did-it-settle" class="level2">
<h2 class="anchored" data-anchor-id="convergence-did-it-settle">Convergence: did it settle?</h2>
<p>Because every run starts from random coordinates, one NMDS could land on a poor arrangement by chance. <code>metaMDS()</code> guards against that by repeating the fit and checking whether the best arrangement keeps coming back. A summary line like <code>Best solution was repeated 11 times in 20 tries</code> is the reassurance: when most of the starts reach the same configuration, the result is unlikely to be a quirk of one random seed. If instead you see no convergent solutions, or a best solution found only once, raise <code>trymax</code> and treat the result as provisional until it stabilises.</p>
</section>
<section id="reading-the-map" class="level2">
<h2 class="anchored" data-anchor-id="reading-the-map">Reading the map</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">site_sc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scores</span>(ord, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">display =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sites"</span>))</span>
<span id="cb12-2">site_sc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>moisture <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> gradient</span>
<span id="cb12-3">spec_sc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scores</span>(ord, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">display =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"species"</span>))</span>
<span id="cb12-4">spec_sc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>species <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(spec_sc)</span></code></pre></div></div>
</div>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(site_sc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(NMDS1, NMDS2)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#dad9ca"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_vline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#dad9ca"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> spec_sc, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> species),</span>
<span id="cb13-5">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#9a6a2f"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fontface =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"italic"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> moisture), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_text</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Site"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(site_sc))),</span>
<span id="cb13-8">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fontface =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_gradient</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">low =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#c9b458"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">high =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1d5b4e"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Moisture"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_equal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb13-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-ord" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Scatter plot of the sixteen sites in two NMDS dimensions, coloured from gold for dry to green for wet. The sites are arranged left to right along the first axis in order of moisture. Species names sit near the sites where they are most abundant, with dry-ground plants on the left, wetland plants on the right, and generalists in the middle.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-ord-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/nmds-ordination/index_files/figure-html/fig-ord-1.png" class="img-fluid figure-img" alt="Scatter plot of the sixteen sites in two NMDS dimensions, coloured from gold for dry to green for wet. The sites are arranged left to right along the first axis in order of moisture. Species names sit near the sites where they are most abundant, with dry-ground plants on the left, wetland plants on the right, and generalists in the middle." width="720">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-ord-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Sites in NMDS space, coloured by their true moisture position. Composition turns over along the first axis.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The sites are coloured by their true position on the moisture gradient, the one piece of information NMDS never saw. They line up almost cleanly along the first axis, dry gold on the left, wet green on the right. We can attach a number to that:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(site_sc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>NMDS1, site_sc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>moisture))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.9305619</code></pre>
</div>
</div>
<p>A correlation around 0.93 between the first axis and the real gradient, recovered from nothing but the species counts. The sign of an NMDS axis is arbitrary, so left versus right carries no meaning beyond the ordering itself. The species labels say the same thing from the other direction: the dry-ground plants (Thymus, Sedum) sit at one end, the sedges and rushes (Carex, Juncus) at the other, and the three generalists fall near the centre, because turning up everywhere is much the same as preferring nowhere.</p>
</section>
<section id="where-to-go-next" class="level2">
<h2 class="anchored" data-anchor-id="where-to-go-next">Where to go next</h2>
<p>NMDS hands you the picture; the natural follow-ups put statistics on it. <code>envfit()</code> overlays measured environmental variables as arrows, so you can ask which of them align with the ordination axes. <code>adonis2()</code> runs PERMANOVA, testing whether groups of sites differ in composition more than chance would allow, which is the formal counterpart to seeing clusters by eye. Both work from the same dissimilarity matrix you already built here.</p>


<!-- -->

</section>

 ]]></description>
  <category>R</category>
  <category>vegan</category>
  <category>ordination</category>
  <category>community ecology</category>
  <guid>https://tidyecology.com/posts/nmds-ordination/</guid>
  <pubDate>Thu, 18 Jun 2026 21:00:00 GMT</pubDate>
  <media:content url="https://tidyecology.com/posts/nmds-ordination/thumbnail.png" medium="image" type="image/png" height="110" width="144"/>
</item>
<item>
  <title>Computing diversity indices in R with vegan</title>
  <dc:creator>Tidy Ecology</dc:creator>
  <link>https://tidyecology.com/posts/diversity-indices-in-r/</link>
  <description><![CDATA[ 





<p>Alpha diversity, meaning how diverse a single site or sample is, is usually the first number an ecologist wants out of a species-abundance table. This post covers the three you’ll reach for most often: <strong>species richness</strong>, the <strong>Shannon index</strong>, and the <strong>Simpson index</strong>, all from the <code>vegan</code> package.</p>
<p>We’ll go from a raw community matrix to a tidy results table and a finished plot.</p>
<section id="a-community-matrix" class="level2">
<h2 class="anchored" data-anchor-id="a-community-matrix">A community matrix</h2>
<p><code>vegan</code> expects a <strong>community matrix</strong>: one row per site (or sample), one column per species, cells holding abundances (counts or cover). Here’s a small worked example, with counts of five plant species across four meadow plots:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(vegan)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-4"></span>
<span id="cb1-5">community <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb1-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Plot_A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Plot_B"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Plot_C"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Plot_D"</span>),</span>
<span id="cb1-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Festuca   =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb1-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Trifolium =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>( <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>),</span>
<span id="cb1-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Plantago  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>( <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>),</span>
<span id="cb1-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Achillea  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>( <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>),</span>
<span id="cb1-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Lotus     =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>( <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb1-12">)</span>
<span id="cb1-13"></span>
<span id="cb1-14">community</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>       Festuca Trifolium Plantago Achillea Lotus
Plot_A      10         8        5        2     0
Plot_B       0        12        3        9    15
Plot_C      25         2        1        0     0
Plot_D       4         5        6        5     4</code></pre>
</div>
</div>
<p>Each row is a plot; each column a species. <code>Plot_C</code> is dominated by <em>Festuca</em>, while <code>Plot_D</code> spreads its individuals evenly across all five species.</p>
</section>
<section id="the-three-indices" class="level2">
<h2 class="anchored" data-anchor-id="the-three-indices">The three indices</h2>
<p><code>vegan</code> gives you each of these in a single call:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">richness <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">specnumber</span>(community)                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of species present</span></span>
<span id="cb3-2">shannon  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diversity</span>(community, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">index =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shannon"</span>)</span>
<span id="cb3-3">simpson  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diversity</span>(community, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">index =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"simpson"</span>)</span>
<span id="cb3-4"></span>
<span id="cb3-5">richness</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Plot_A Plot_B Plot_C Plot_D 
     4      4      3      5 </code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">shannon</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>   Plot_A    Plot_B    Plot_C    Plot_D 
1.2550811 1.2658568 0.4086977 1.5974167 </code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">simpson</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>   Plot_A    Plot_B    Plot_C    Plot_D 
0.6912000 0.6982249 0.1964286 0.7951389 </code></pre>
</div>
</div>
<p>A few things worth knowing:</p>
<ul>
<li><strong><code>specnumber()</code></strong> simply counts the non-zero species. It’s the most basic measure, and blind to abundance.</li>
<li><strong>Shannon (H′)</strong> rises with both richness <em>and</em> evenness; for real communities it usually falls between about 1.5 and 3.5.</li>
<li><strong>Simpson</strong> is returned here as 1 − D: the probability that two individuals drawn at random belong to <em>different</em> species. It runs from 0 to 1 and is less sensitive to rare species than Shannon.</li>
</ul>
</section>
<section id="a-tidy-results-table" class="level2">
<h2 class="anchored" data-anchor-id="a-tidy-results-table">A tidy results table</h2>
<p>Let’s pull everything into one data frame, rounded for reading:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">diversity_summary <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb9-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot     =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(community),</span>
<span id="cb9-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">richness =</span> richness,</span>
<span id="cb9-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shannon  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(shannon, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb9-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">simpson  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(simpson, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb9-6">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb9-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">desc</span>(shannon))</span>
<span id="cb9-8"></span>
<span id="cb9-9">diversity_summary</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code># A tibble: 4 × 4
  plot   richness shannon simpson
  &lt;chr&gt;     &lt;int&gt;   &lt;dbl&gt;   &lt;dbl&gt;
1 Plot_D        5    1.6     0.8 
2 Plot_B        4    1.27    0.7 
3 Plot_A        4    1.26    0.69
4 Plot_C        3    0.41    0.2 </code></pre>
</div>
</div>
<p><code>Plot_D</code> comes out most diverse. It carries all five species at similar abundances, so its evenness is high. <code>Plot_A</code> and <code>Plot_B</code> land in the middle and almost tie (1.26 vs 1.27), despite very different species makeups. <code>Plot_C</code>, dominated by a single grass, scores lowest even though three species are present. That gap between <em>richness</em> and <em>Shannon</em> is the evenness effect at work.</p>
</section>
<section id="a-plot" class="level2">
<h2 class="anchored" data-anchor-id="a-plot">A plot</h2>
<p>Finally, the bit you’ll actually paste into a report: Shannon diversity per plot.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(diversity_summary, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reorder</span>(plot, shannon), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> shannon)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2f6b3e"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_text</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> shannon), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_flip</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Shannon diversity (H′)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ylim</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(diversity_summary<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>shannon) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.15</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="fig-shannon" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-shannon-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://tidyecology.com/posts/diversity-indices-in-r/index_files/figure-html/fig-shannon-1.png" class="img-fluid figure-img" width="576">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-shannon-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Shannon diversity (H′) across the four meadow plots.
</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="where-to-go-next" class="level2">
<h2 class="anchored" data-anchor-id="where-to-go-next">Where to go next</h2>
<p>This is the foundation. Realistic next steps:</p>
<ul>
<li>swap the toy matrix for your own data, read in with <code>read.csv()</code> into the same site-by-species shape;</li>
<li>add <strong>Pielou’s evenness</strong> (<code>shannon / log(richness)</code>) to separate richness from evenness explicitly;</li>
<li>once you have many sites, move from alpha to <strong>beta diversity</strong> and ordination (<code>vegdist()</code>, <code>metaMDS()</code>).</li>
</ul>
<p>Ordination is the next post. If you hit a snag adapting this to your own data, <a href="../../contact.html">let me know</a>.</p>


<!-- -->

</section>

 ]]></description>
  <category>R</category>
  <category>biodiversity</category>
  <category>tutorial</category>
  <guid>https://tidyecology.com/posts/diversity-indices-in-r/</guid>
  <pubDate>Wed, 17 Jun 2026 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Welcome to Tidy Ecology</title>
  <dc:creator>Tidy Ecology</dc:creator>
  <link>https://tidyecology.com/posts/welcome/</link>
  <description><![CDATA[ 





<p><strong>Tidy Ecology</strong> collects the R and QGIS workflows behind real ecological and biodiversity work, written the way they’re easiest to actually use: reproducible, honest about the rough edges, and built around real questions rather than toy datasets.</p>
<p>Posts coming up will work through things like getting clean occurrence data out of GBIF and iNaturalist, the standard alpha- and beta-diversity toolkit in <code>vegan</code>, species distribution models from first principles, and spatial workflows that move smoothly between R and QGIS.</p>
<p>Everything comes with code you can copy, adapt, and break on your own data.</p>
<p>Stuck on a topic? The <a href="../../contact.html">contact page</a> is open. The first proper tutorial is already up: <a href="../diversity-indices-in-r/">diversity indices in R</a>.</p>


<!-- -->


 ]]></description>
  <category>meta</category>
  <guid>https://tidyecology.com/posts/welcome/</guid>
  <pubDate>Tue, 16 Jun 2026 21:00:00 GMT</pubDate>
</item>
</channel>
</rss>
