<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Chatterjee Xi | Thiago Oliveira</title>
    <link>https://prof-thiagooliveira.netlify.app/tags/chatterjee-xi/</link>
      <atom:link href="https://prof-thiagooliveira.netlify.app/tags/chatterjee-xi/index.xml" rel="self" type="application/rss+xml" />
    <description>Chatterjee Xi</description>
    <generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Sun, 27 Sep 2026 00:00:00 +0000</lastBuildDate>
    <image>
      <url>https://prof-thiagooliveira.netlify.app/media/logo_hua8192a3d26f52862b6ecd0fa00b0dcdd_44669_300x300_fit_lanczos_3.png</url>
      <title>Chatterjee Xi</title>
      <link>https://prof-thiagooliveira.netlify.app/tags/chatterjee-xi/</link>
    </image>
    
    <item>
      <title>Beyond Pearson. What else can we learn about the relationship between two variables?</title>
      <link>https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/</link>
      <pubDate>Sun, 27 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/</guid>
      <description>

&lt;div id=&#34;TOC&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#pearson-correlation-as-a-starting-point&#34; id=&#34;toc-pearson-correlation-as-a-starting-point&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;1&lt;/span&gt; Pearson correlation as a starting point&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#different-questions-about-dependence&#34; id=&#34;toc-different-questions-about-dependence&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;2&lt;/span&gt; Different questions about dependence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#linear-association-and-the-gaussian-case&#34; id=&#34;toc-linear-association-and-the-gaussian-case&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;3&lt;/span&gt; Linear association and the Gaussian case&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#monotonic-but-nonlinear-relationships&#34; id=&#34;toc-monotonic-but-nonlinear-relationships&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;4&lt;/span&gt; Monotonic but nonlinear relationships&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#dependence-with-zero-linear-correlation&#34; id=&#34;toc-dependence-with-zero-linear-correlation&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;5&lt;/span&gt; Dependence with zero linear correlation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#directional-dependence&#34; id=&#34;toc-directional-dependence&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;6&lt;/span&gt; Directional dependence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#sensitivity-to-the-observed-sample&#34; id=&#34;toc-sensitivity-to-the-observed-sample&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;7&lt;/span&gt; Sensitivity to the observed sample&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#influential-observations&#34; id=&#34;toc-influential-observations&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;7.1&lt;/span&gt; Influential observations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#range-restriction&#34; id=&#34;toc-range-restriction&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;7.2&lt;/span&gt; Range restriction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#marginal-and-partial-correlation&#34; id=&#34;toc-marginal-and-partial-correlation&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;8&lt;/span&gt; Marginal and partial correlation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-remarks&#34; id=&#34;toc-final-remarks&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;9&lt;/span&gt; Final remarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#references&#34; id=&#34;toc-references&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;10&lt;/span&gt; References&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#reproducibility&#34; id=&#34;toc-reproducibility&#34;&gt;&lt;span class=&#34;toc-section-number&#34;&gt;11&lt;/span&gt; Reproducibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;div id=&#34;pearson-correlation-as-a-starting-point&#34; class=&#34;section level1&#34; number=&#34;1&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;1&lt;/span&gt; Pearson correlation as a starting point&lt;/h1&gt;
&lt;p&gt;If someone asks for the correlation between two continuous variables, the default answer is usually Pearson’s correlation coefficient. It is familiar, interpretable and closely connected to linear regression. Given two variables &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho_{XY} =
\frac{\operatorname{Cov}(X,Y)}{\sigma_X\sigma_Y}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Its question is precise.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;To what extent do &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; vary together linearly?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The figure below shows several different data generating mechanisms. Pearson’s &lt;span class=&#34;math inline&#34;&gt;\(r\)&lt;/span&gt; ranges from about 0.61 to 0.78. All five coefficients indicate positive linear association, but the scatterplots show substantial differences in curvature, conditional spread, group structure and influential observations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/opening-figure-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Pearson compresses the joint distribution into a summary of second moments. To make this precise, suppose both variables have finite, nonzero variances. Write &lt;span class=&#34;math inline&#34;&gt;\(\mu_X=E(X)\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(\mu_Y=E(Y)\)&lt;/span&gt;, and define the standardised variables &lt;span class=&#34;math inline&#34;&gt;\(Z_X=(X-\mu_X)/\sigma_X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Z_Y=(Y-\mu_Y)/\sigma_Y\)&lt;/span&gt;. Then&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho_{XY}
=
\frac{E(XY)-\mu_X\mu_Y}{\sigma_X\sigma_Y}
=
E(Z_XZ_Y).
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The means, variances and mixed second moment &lt;span class=&#34;math inline&#34;&gt;\(E(XY)\)&lt;/span&gt; are the only features of the joint distribution entering this calculation. Here &lt;span class=&#34;math inline&#34;&gt;\(\sigma_X^2=E(X^2)-\mu_X^2\)&lt;/span&gt;, and similarly for &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;. Different joint distributions can share all these moments and therefore have exactly the same Pearson correlation. The sample coefficient &lt;span class=&#34;math inline&#34;&gt;\(r\)&lt;/span&gt; is the analogous normalised sum of centred products.&lt;/p&gt;
&lt;details class=&#34;article-note&#34;&gt;
&lt;summary&gt;
Example with identical moments
&lt;/summary&gt;
&lt;div class=&#34;article-note-body&#34;&gt;
&lt;p&gt;Let &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; take the values &lt;span class=&#34;math inline&#34;&gt;\(-1\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(0\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(1\)&lt;/span&gt;, each with probability &lt;span class=&#34;math inline&#34;&gt;\(1/3\)&lt;/span&gt;. Compare two ways to generate &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dependent pair.&lt;/strong&gt; Set &lt;span class=&#34;math inline&#34;&gt;\(Y=X^2\)&lt;/span&gt;. The three equally likely pairs are &lt;span class=&#34;math inline&#34;&gt;\((-1,1)\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\((0,0)\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\((1,1)\)&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Independent pair.&lt;/strong&gt; Draw &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; independently of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;, with &lt;span class=&#34;math inline&#34;&gt;\(P(Y=1)=2/3\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(P(Y=0)=1/3\)&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both constructions give exactly the same marginal distributions for &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;, so their marginal means and variances are identical. They also have the same mixed second moment. For the dependent pair,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
E(XY)=\frac{(-1)(1)+(0)(0)+(1)(1)}{3}=0.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For the independent pair, &lt;span class=&#34;math inline&#34;&gt;\(E(XY)=E(X)E(Y)=0\)&lt;/span&gt;, because &lt;span class=&#34;math inline&#34;&gt;\(E(X)=0\)&lt;/span&gt;. Thus both have zero covariance and Pearson correlation zero.&lt;/p&gt;
&lt;p&gt;The difference is easy to see. In the dependent pair, knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; tells us &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; exactly. In the independent pair, knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; does not change the probabilities of &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;. Their moments agree, but their joint distributions do not.&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;Pearson cannot by itself tell us whether the conditional mean is curved, whether conditional variance changes with &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;, whether the population contains distinct groups, or whether a few observations exert unusual influence.&lt;/p&gt;
&lt;p&gt;The heteroscedastic panel illustrates the conditional variance issue. Similar &lt;span class=&#34;math inline&#34;&gt;\(r\)&lt;/span&gt; can accompany very different &lt;span class=&#34;math inline&#34;&gt;\(\operatorname{Var}(Y\mid X)\)&lt;/span&gt;, as the following population example makes explicit.&lt;/p&gt;
&lt;details class=&#34;article-note&#34;&gt;
&lt;summary&gt;
Example of heteroscedasticity
&lt;/summary&gt;
&lt;div class=&#34;article-note-body&#34;&gt;
&lt;p&gt;Let &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(\varepsilon_1\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(\varepsilon_2\)&lt;/span&gt; be independent standard normal variables. Compare&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
Y_1=X+\varepsilon_1,
\qquad
Y_2=X+X\varepsilon_2.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Both have the same conditional mean, &lt;span class=&#34;math inline&#34;&gt;\(E(Y_1\mid X)=E(Y_2\mid X)=X\)&lt;/span&gt;. Their conditional variances differ.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\operatorname{Var}(Y_1\mid X)=1,
\qquad
\operatorname{Var}(Y_2\mid X)=X^2.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The first relationship has constant vertical spread. The second is tight near &lt;span class=&#34;math inline&#34;&gt;\(X=0\)&lt;/span&gt; and becomes more variable as &lt;span class=&#34;math inline&#34;&gt;\(|X|\)&lt;/span&gt; increases.&lt;/p&gt;
&lt;p&gt;Nevertheless, both have &lt;span class=&#34;math inline&#34;&gt;\(\operatorname{Cov}(X,Y_i)=1\)&lt;/span&gt;. By the law of total variance,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\operatorname{Var}(Y_i)
=\operatorname{Var}\{E(Y_i\mid X)\}
+E\{\operatorname{Var}(Y_i\mid X)\}
=1+1=2,
\qquad i=1,2.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For &lt;span class=&#34;math inline&#34;&gt;\(Y_2\)&lt;/span&gt;, the second term is &lt;span class=&#34;math inline&#34;&gt;\(E(X^2)=1\)&lt;/span&gt;. Hence the two population Pearson correlations are exactly equal.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho_{X,Y_1}=\rho_{X,Y_2}=\frac{1}{\sqrt{2}}\approx 0.707.
\]&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;The simulations below use fixed seeds and moderately sized samples. Each introduces a feature of dependence that the preceding summaries leave unresolved.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;different-questions-about-dependence&#34; class=&#34;section level1&#34; number=&#34;2&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;2&lt;/span&gt; Different questions about dependence&lt;/h1&gt;
&lt;p&gt;The measures correspond to different statistical questions.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Statistical question&lt;/th&gt;
&lt;th&gt;Measure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Do &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; vary together linearly?&lt;/td&gt;
&lt;td&gt;Pearson correlation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Do larger values of one variable tend to correspond monotonically to larger or smaller values of the other?&lt;/td&gt;
&lt;td&gt;Spearman correlation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Do pairs of observations tend to preserve the same ordering?&lt;/td&gt;
&lt;td&gt;Kendall’s &lt;span class=&#34;math inline&#34;&gt;\(\tau\)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Is there dependence, including nonlinear or nonmonotonic dependence?&lt;/td&gt;
&lt;td&gt;Distance correlation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Is there dependence detectable through flexible kernel representations?&lt;/td&gt;
&lt;td&gt;HSIC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;How strongly does &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; depend on &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;, allowing the two directions to differ?&lt;/td&gt;
&lt;td&gt;Chatterjee’s &lt;span class=&#34;math inline&#34;&gt;\(\xi\)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Does the apparent association persist when unusual observations have limited influence?&lt;/td&gt;
&lt;td&gt;Robust correlation estimators&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Does linear association remain after adjusting for other variables?&lt;/td&gt;
&lt;td&gt;Partial correlation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For this article, I use the following organisation as a teaching device rather than as a formal taxonomy.&lt;/p&gt;
&lt;pre class=&#34;text&#34;&gt;&lt;code&gt;Questions about dependence
|
+-- Linear association
|   +-- Pearson
|
+-- Monotonic ordering
|   +-- Spearman
|   +-- Kendall
|
+-- General dependence
|   +-- Distance correlation
|   +-- HSIC
|
+-- Directional dependence
|   +-- Chatterjee&amp;#39;s xi
|
+-- Sensitivity to observations
|   +-- Robust correlations
|
+-- Conditional association
    +-- Partial correlation&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;linear-association-and-the-gaussian-case&#34; class=&#34;section level1&#34; number=&#34;3&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;3&lt;/span&gt; Linear association and the Gaussian case&lt;/h1&gt;
&lt;p&gt;Pearson is closely linked to linear regression. In ordinary simple linear regression with an intercept, &lt;span class=&#34;math inline&#34;&gt;\(r^2 = R^2\)&lt;/span&gt;. This is one reason Pearson correlation is such a natural summary when the relationship is genuinely linear.&lt;/p&gt;
&lt;p&gt;Pearson is invariant to changes of location and scale. If we add constants or multiply both variables by positive constants, &lt;span class=&#34;math inline&#34;&gt;\(r\)&lt;/span&gt; does not change. Multiplying one variable by a negative constant reverses the sign.&lt;/p&gt;
&lt;p&gt;To calibrate the measures against a known population model, start with a jointly Gaussian pair with a specified Pearson correlation. We use the construction&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
X \sim N(0,1), \qquad
Y = \rho X + \sqrt{1-\rho^2}\varepsilon,
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class=&#34;math inline&#34;&gt;\(\varepsilon\sim N(0,1)\)&lt;/span&gt; is independent of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;, and we set &lt;span class=&#34;math inline&#34;&gt;\(\rho=0.7\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The coefficients are chosen to keep both variables centred with unit variance. Independence gives&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\begin{aligned}
\operatorname{Var}(Y)&amp;amp;=\rho^2+(1-\rho^2)=1,\\
\operatorname{Cov}(X,Y)&amp;amp;=\rho\operatorname{Var}(X)=\rho.
\end{aligned}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As a linear combination of independent normal variables, &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; has the marginal distribution&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
Y\sim N\!\left(0,\rho^2+(1-\rho^2)\right)=N(0,1).
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Since both standard deviations equal one, &lt;span class=&#34;math inline&#34;&gt;\(\operatorname{Cor}(X,Y)=\rho\)&lt;/span&gt;. The factor &lt;span class=&#34;math inline&#34;&gt;\(\sqrt{1-\rho^2}\)&lt;/span&gt; scales the independent noise so that changing &lt;span class=&#34;math inline&#34;&gt;\(\rho\)&lt;/span&gt; changes the dependence while preserving the marginal variance. These assumptions define the calibration example; they require separate justification when modelling real data.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/baseline-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;For this simulated sample, Pearson’s &lt;span class=&#34;math inline&#34;&gt;\(r\)&lt;/span&gt; is 0.735, compared with the generating population correlation &lt;span class=&#34;math inline&#34;&gt;\(\rho=0.7\)&lt;/span&gt;. The difference reflects sampling variability.&lt;/p&gt;
&lt;p&gt;To obtain the joint distribution, write the construction as a matrix transformation.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\begin{pmatrix}X\\Y\end{pmatrix}
=A\begin{pmatrix}X\\\varepsilon\end{pmatrix},
\qquad
A=\begin{pmatrix}
1 &amp;amp; 0\\
\rho &amp;amp; \sqrt{1-\rho^2}
\end{pmatrix}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Independence gives &lt;span class=&#34;math inline&#34;&gt;\((X,\varepsilon)^{\mathsf T}\sim N_2(\mathbf{0},I_2)\)&lt;/span&gt;. A linear transformation of a multivariate normal vector is also multivariate normal. Its mean vector is &lt;span class=&#34;math inline&#34;&gt;\(A\mathbf{0}=\mathbf{0}\)&lt;/span&gt; and its covariance matrix is&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
AI_2A^{\mathsf T}=AA^{\mathsf T}
=\begin{pmatrix}
1 &amp;amp; \rho\\
\rho &amp;amp; \rho^2+(1-\rho^2)
\end{pmatrix}
=\begin{pmatrix}
1 &amp;amp; \rho\\
\rho &amp;amp; 1
\end{pmatrix}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Therefore,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\begin{pmatrix}
X \\
Y
\end{pmatrix}
\sim
N_2
\left[
\begin{pmatrix}
0 \\
0
\end{pmatrix},
\begin{pmatrix}
1 &amp;amp; \rho \\
\rho &amp;amp; 1
\end{pmatrix}
\right].
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For this jointly Gaussian model,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho = 0 \iff X \perp Y.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Under bivariate normality, means, variances and Pearson’s &lt;span class=&#34;math inline&#34;&gt;\(\rho\)&lt;/span&gt; determine the joint distribution. After standardisation, &lt;span class=&#34;math inline&#34;&gt;\(\rho\)&lt;/span&gt; is the single free dependence parameter. This requires joint normality; two variables can each be marginally normal without being jointly normal. The rank correlations are deterministic functions of &lt;span class=&#34;math inline&#34;&gt;\(\rho\)&lt;/span&gt; (&lt;a href=&#34;https://doi.org/10.1037/met0000079&#34;&gt;de Winter, Gosling and Potter, 2016, equations 9 and 10&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\tau=\frac{2}{\pi}\arcsin(\rho),
\qquad
\rho_S=\frac{6}{\pi}\arcsin\left(\frac{\rho}{2}\right).
\]&lt;/span&gt;&lt;/p&gt;
&lt;details class=&#34;article-note&#34;&gt;
&lt;summary&gt;
Converting Gaussian correlation measures
&lt;/summary&gt;
&lt;div class=&#34;article-note-body&#34;&gt;
&lt;p&gt;For a bivariate normal population with Pearson correlation &lt;span class=&#34;math inline&#34;&gt;\(\rho=0.7\)&lt;/span&gt;, the corresponding rank correlations are&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\begin{aligned}
\tau&amp;amp;=\frac{2}{\pi}\arcsin(0.7)\approx 0.494,\\
\rho_S&amp;amp;=\frac{6}{\pi}\arcsin(0.7/2)\approx 0.683.
\end{aligned}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The inverse functions recover Pearson correlation from either rank coefficient.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\begin{aligned}
\rho&amp;amp;=\sin\!\left(\frac{\pi\tau}{2}\right),\\
\rho&amp;amp;=2\sin\!\left(\frac{\pi\rho_S}{6}\right).
\end{aligned}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Population distance correlation also has an exact Gaussian relation (&lt;a href=&#34;https://doi.org/10.1214/009053607000000505&#34;&gt;Székely, Rizzo and Bakirov, 2007, Theorem 7&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\operatorname{dCor}^2(X,Y)=
\frac{
\rho\arcsin(\rho)+\sqrt{1-\rho^2}
-\rho\arcsin(\rho/2)-\sqrt{4-\rho^2}+1
}{1+\pi/3-\sqrt{3}}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Taking the nonnegative square root gives dCor. For &lt;span class=&#34;math inline&#34;&gt;\(\rho=0.7\)&lt;/span&gt;, dCor is approximately 0.650. The same value results from &lt;span class=&#34;math inline&#34;&gt;\(\rho=-0.7\)&lt;/span&gt;. Under this model, dCor determines &lt;span class=&#34;math inline&#34;&gt;\(|\rho|\)&lt;/span&gt; but cannot recover its sign.&lt;/p&gt;
&lt;p&gt;The following R function accepts population Pearson, Spearman or Kendall correlation and returns all three plus population dCor. Applying these relations to sample coefficients imposes the Gaussian model and need not reproduce the other estimates from that sample. The converted dCor is a population model value, distinct from an empirical distance correlation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;gaussian_correlations &amp;lt;- function (value, from = c(&amp;quot;pearson&amp;quot;, &amp;quot;spearman&amp;quot;, &amp;quot;kendall&amp;quot;)) 
{
    from &amp;lt;- match.arg(from)
    if (!is.numeric(value) || length(value) == 0L || any(!is.finite(value)) || 
        any(abs(value) &amp;gt; 1)) {
        stop(&amp;quot;value must contain finite numeric correlations between -1 and 1.&amp;quot;, 
            call. = FALSE)
    }
    rho &amp;lt;- switch(from, pearson = value, spearman = 2 * sin(pi * value/6), kendall = sin(pi * 
        value/2))
    rho[abs(value) == 1] &amp;lt;- sign(value[abs(value) == 1])
    dcor_squared &amp;lt;- (rho * (asin(rho) - asin(rho/2)) + rho^2 * (1/(2 + sqrt(4 - 
        rho^2)) - 1/(1 + sqrt(1 - rho^2))))/(1 + pi/3 - sqrt(3))
    data.frame(pearson = rho, spearman = 6/pi * asin(rho/2), kendall = 2/pi * 
        asin(rho), dcor = sqrt(pmax(0, pmin(1, dcor_squared))))
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, start from Pearson and then convert back from each rank coefficient using the unrounded values.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;gaussian_example &amp;lt;- gaussian_correlations(0.7, from = &amp;quot;pearson&amp;quot;)
gaussian_from_s &amp;lt;- gaussian_correlations(gaussian_example$spearman, from = &amp;quot;spearman&amp;quot;)
gaussian_from_k &amp;lt;- gaussian_correlations(gaussian_example$kendall, from = &amp;quot;kendall&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;Input&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Pearson&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Spearman&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Kendall&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;dCor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Pearson&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.683&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.494&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Spearman&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.683&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.494&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Kendall&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.683&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.494&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.65&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;The next figure compares simulated estimates with their Gaussian reference curves across &lt;span class=&#34;math inline&#34;&gt;\(\rho\in[-1,1]\)&lt;/span&gt;. The horizontal axis is the generating Pearson parameter. The signed coefficients range from &lt;span class=&#34;math inline&#34;&gt;\(-1\)&lt;/span&gt; to &lt;span class=&#34;math inline&#34;&gt;\(1\)&lt;/span&gt;, whereas dCor reaches &lt;span class=&#34;math inline&#34;&gt;\(1\)&lt;/span&gt; at both endpoints and has a symmetric population curve with minimum zero at independence.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/gaussian-special-case-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;monotonic-but-nonlinear-relationships&#34; class=&#34;section level1&#34; number=&#34;4&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;4&lt;/span&gt; Monotonic but nonlinear relationships&lt;/h1&gt;
&lt;p&gt;Now simulate a relationship that is clearly increasing but not straight.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
Y = \exp(aX) + \varepsilon.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/monotonic-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;An increasing function preserves order in the sense that&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
x_1&amp;lt;x_2 \quad\Longrightarrow\quad g(x_1)\leq g(x_2).
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For a strictly increasing function, &lt;span class=&#34;math inline&#34;&gt;\(x_1&amp;lt;x_2\Longrightarrow g(x_1)&amp;lt;g(x_2)\)&lt;/span&gt;. When &lt;span class=&#34;math inline&#34;&gt;\(a&amp;gt;0\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(g(x)=\exp(ax)\)&lt;/span&gt; is strictly increasing because &lt;span class=&#34;math inline&#34;&gt;\(g&amp;#39;(x)=a\exp(ax)&amp;gt;0\)&lt;/span&gt;, but it is nonlinear. Monotonicity describes ordering, whereas linearity describes an affine form.&lt;/p&gt;
&lt;p&gt;Without noise, a deterministic relationship &lt;span class=&#34;math inline&#34;&gt;\(Y=g(X)\)&lt;/span&gt; with &lt;span class=&#34;math inline&#34;&gt;\(g\)&lt;/span&gt; strictly increasing and continuous variables gives identical orderings of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;. Consequently,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho_S=1,\qquad \tau=1.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For Pearson, assuming finite, nonzero variances,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
|\rho_{XY}|=1
\quad\Longleftrightarrow\quad
Y=\alpha+\beta X\ \text{almost surely},\qquad \beta\neq0.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The deterministic curve &lt;span class=&#34;math inline&#34;&gt;\(Y=\exp(X)\)&lt;/span&gt; is therefore perfectly monotonic without being perfectly linearly correlated, whenever Pearson correlation is defined for the continuous distribution of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;. In the simulation above, noise can reverse the ordering of individual observations, so the rank correlations need not equal one.&lt;/p&gt;
&lt;p&gt;For continuous variables, population Spearman correlation is&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho_S
=\operatorname{Cor}\{F_X(X),F_Y(Y)\}
=12E\{F_X(X)F_Y(Y)\}-3.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The second equality follows because both marginal distribution transforms are uniform on &lt;span class=&#34;math inline&#34;&gt;\((0,1)\)&lt;/span&gt;. In a sample,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\hat\rho_S=\operatorname{Cor}\{R(X),R(Y)\},
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class=&#34;math inline&#34;&gt;\(R(X)\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(R(Y)\)&lt;/span&gt; are the sample ranks. Spearman’s correlation is Pearson correlation applied to ranks.&lt;/p&gt;
&lt;p&gt;If &lt;span class=&#34;math inline&#34;&gt;\(g\)&lt;/span&gt; is strictly increasing, then, in the absence of ties,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
R\{g(X)\}=R(X),
\qquad
\rho_S\{g(X),Y\}=\rho_S(X,Y).
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A strictly increasing transformation of either variable preserves Spearman correlation. A strictly decreasing transformation of one variable reverses its sign. This invariance does not extend to arbitrary nonlinear transformations. Spearman specifically measures monotonic rank association, rather than general nonlinear dependence.&lt;/p&gt;
&lt;p&gt;Kendall compares the orderings of two independent copies &lt;span class=&#34;math inline&#34;&gt;\((X_1,Y_1)\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\((X_2,Y_2)\)&lt;/span&gt;. They are concordant when &lt;span class=&#34;math inline&#34;&gt;\((X_1-X_2)(Y_1-Y_2)&amp;gt;0\)&lt;/span&gt; and discordant when &lt;span class=&#34;math inline&#34;&gt;\((X_1-X_2)(Y_1-Y_2)&amp;lt;0\)&lt;/span&gt;. For continuous variables without ties,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\begin{aligned}
\tau
&amp;amp;=P(\text{concordant})-P(\text{discordant})\\
&amp;amp;=E\!\left[\operatorname{sign}\{(X_1-X_2)(Y_1-Y_2)\}\right].
\end{aligned}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Kendall’s &lt;span class=&#34;math inline&#34;&gt;\(\tau\)&lt;/span&gt; compares how often randomly selected pairs are ordered consistently in &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; with how often the ordering is reversed.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Measure&lt;/th&gt;
&lt;th&gt;What is compared?&lt;/th&gt;
&lt;th&gt;Main feature&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Pearson&lt;/td&gt;
&lt;td&gt;Original values&lt;/td&gt;
&lt;td&gt;Linear association&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Spearman&lt;/td&gt;
&lt;td&gt;Ranks&lt;/td&gt;
&lt;td&gt;Monotonic association&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Kendall&lt;/td&gt;
&lt;td&gt;Pairwise concordance&lt;/td&gt;
&lt;td&gt;Pairwise ordering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In this simulation, Pearson’s &lt;span class=&#34;math inline&#34;&gt;\(r=0.807\)&lt;/span&gt;, Spearman’s &lt;span class=&#34;math inline&#34;&gt;\(\hat\rho_S=0.857\)&lt;/span&gt; and Kendall’s &lt;span class=&#34;math inline&#34;&gt;\(\hat\tau=0.677\)&lt;/span&gt;. Spearman remains high, consistent with the strong monotonic ordering visible in the scatterplot, and positive Kendall indicates that concordant pairs are more frequent than discordant pairs. The curve and the coefficients together describe strong positive ordering despite the noise. Pearson and Spearman estimate different population functionals, so their numerical difference is not a direct measure of curvature.&lt;/p&gt;
&lt;details class=&#34;article-note&#34;&gt;
&lt;summary&gt;
Technical note on ties
&lt;/summary&gt;
&lt;div class=&#34;article-note-body&#34;&gt;
&lt;p&gt;Real data can contain ties because of rounding, ordinal scales or discrete measurements. In &lt;code&gt;matrixCorr&lt;/code&gt;, Spearman uses average ranks, also called midranks, and Kendall uses &lt;span class=&#34;math inline&#34;&gt;\(\tau_b\)&lt;/span&gt; to adjust for ties, reducing to &lt;span class=&#34;math inline&#34;&gt;\(\tau_a\)&lt;/span&gt; when there are none. Chatterjee’s &lt;span class=&#34;math inline&#34;&gt;\(\xi\)&lt;/span&gt; has its own handling of response ties and an explicit rule for breaking ties in the sorting variable. The tie rule should be part of the analysis.&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;Strong dependence need not preserve ordering, as the quadratic example illustrates.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dependence-with-zero-linear-correlation&#34; class=&#34;section level1&#34; number=&#34;5&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;5&lt;/span&gt; Dependence with zero linear correlation&lt;/h1&gt;
&lt;p&gt;The most important nonmonotonic example here is&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
X \sim N(0,1), \qquad Y = X^2 + \varepsilon.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The simulated noise is independent of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and centred, so &lt;span class=&#34;math inline&#34;&gt;\(E(\varepsilon)=0\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(\varepsilon\perp X\)&lt;/span&gt;. Because the standard normal distribution is symmetric,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\operatorname{Cov}(X,X^2)
=
E(X^3)-E(X)E(X^2)
=
0.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For the actual response,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\begin{aligned}
\operatorname{Cov}(X,Y)
&amp;amp;=\operatorname{Cov}(X,X^2)+\operatorname{Cov}(X,\varepsilon)\\
&amp;amp;=0+0\\
&amp;amp;=0.
\end{aligned}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Thus the population Pearson correlation is zero even though the conditional mean of &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; varies with &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/quadratic-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The curve bends back on itself. The increasing and decreasing branches cancel in the linear summary and do not give a consistent global rank ordering.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;pearson&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;spearman&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;kendall&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;dcor&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;hsic&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;xi_y_given_x&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;xi_x_given_y&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;-0.048&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.094&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.073&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.504&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.366&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.589&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Distance covariance compares patterns of pairwise distances. When &lt;span class=&#34;math inline&#34;&gt;\(E|X|&amp;lt;\infty\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(E|Y|&amp;lt;\infty\)&lt;/span&gt;, population distance correlation satisfies (&lt;a href=&#34;https://doi.org/10.1214/009053607000000505&#34;&gt;Székely, Rizzo and Bakirov, 2007&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\operatorname{dCor}(X,Y)=0 \iff X\perp Y.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Kernel methods compare functions of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; rather than only their original values (&lt;a href=&#34;https://jmlr.org/papers/v6/gretton05a.html&#34;&gt;Gretton, Herbrich et al., 2005&lt;/a&gt;). HSIC uses these kernel representations to measure dependence through a cross covariance operator (&lt;a href=&#34;https://www.cs.cmu.edu/~arthurg/papers/GreBouSmoSch05.pdf&#34;&gt;Gretton, Bousquet et al., 2005&lt;/a&gt;). With characteristic kernels such as the Gaussian RBF kernel, population HSIC is zero if and only if the variables are independent (&lt;a href=&#34;https://proceedings.neurips.cc/paper/2007/file/d5cfead94f5350c12c322b5b664544c1-Paper.pdf&#34;&gt;Gretton et al., 2007&lt;/a&gt;; &lt;a href=&#34;https://jmlr.org/papers/v11/sriperumbudur10a.html&#34;&gt;Sriperumbudur et al., 2010&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The tutorial uses Gaussian kernels, the median bandwidth rule, the biased empirical estimator and &lt;code&gt;normalise = TRUE&lt;/code&gt;. Its HSIC values are therefore normalised kernel correlations. Unlike Pearson, there is no empirical HSIC number independent of the kernel and its tuning parameters. The specification is held fixed across scenarios, although the median rule adapts the numerical bandwidth to each sample. The software conventions for both measures are documented under &lt;a href=&#34;#reproducibility&#34;&gt;Reproducibility&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pearson, Spearman and Kendall can be positive or negative. Conventional dCor and the normalised HSIC measure used here are nonnegative and do not assign a global increasing or decreasing direction. Such a sign may have no useful global interpretation for a quadratic or periodic relationship.&lt;/p&gt;
&lt;p&gt;The phenomenon is not specific to a quadratic relationship. Periodic dependence gives another example in which linear and rank summaries can be weak while general dependence remains clear.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
X \sim U(-\pi,\pi), \qquad Y = \sin(2X)+\varepsilon.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/periodic-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;This periodic draw retains moderate negative linear and rank association (&lt;span class=&#34;math inline&#34;&gt;\(r = -0.354\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(\rho_S = -0.342\)&lt;/span&gt;). The scatterplot shows the oscillation that those summaries compress.&lt;/p&gt;
&lt;p&gt;The panels below place the quadratic example alongside the linear, monotonic and periodic scenarios.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/shape-panels-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Distance correlation and HSIC address dependence rather than functional form. Detecting dependence still leaves subsequent modelling to explain its shape. In practice, I would use one of them when independence is the scientific question or when the plotted structure is inadequately described by linear and rank summaries. For an uncomplicated monotonic relationship, an additional general dependence coefficient may add little substantive information.&lt;/p&gt;
&lt;p&gt;The preceding measures are symmetric in their arguments. We can also ask whether knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; informs the distribution of &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; in the same way that knowing &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; informs the distribution of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;directional-dependence&#34; class=&#34;section level1&#34; number=&#34;6&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;6&lt;/span&gt; Directional dependence&lt;/h1&gt;
&lt;p&gt;Chatterjee’s &lt;span class=&#34;math inline&#34;&gt;\(\xi\)&lt;/span&gt; asks how much knowing one variable tells us about the other. The order matters. The call&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;xi_corr(x, y)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;estimates &lt;span class=&#34;math inline&#34;&gt;\(\xi(x, y)\)&lt;/span&gt;, where &lt;code&gt;x&lt;/code&gt; is the sorting or predictor variable and &lt;code&gt;y&lt;/code&gt; is the response or ranked variable. Read this as using &lt;code&gt;x&lt;/code&gt; to learn about &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For nondegenerate &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;, meaning that &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; does not always take the same value, the population target is (&lt;a href=&#34;https://doi.org/10.1080/01621459.2020.1758115&#34;&gt;Chatterjee, 2021, Theorem 1.1&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\xi(X,Y)=
\frac{
\int \operatorname{Var}\!\left[
E\{\mathbf{1}(Y\geq t)\mid X\}
\right] \,dF_Y(t)
}{
\int \operatorname{Var}\{\mathbf{1}(Y\geq t)\} \,dF_Y(t)
}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Read the equation as a collection of yes or no questions. Choose a cutoff &lt;span class=&#34;math inline&#34;&gt;\(t\)&lt;/span&gt; and ask whether &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; is at least that large. The indicator &lt;span class=&#34;math inline&#34;&gt;\(\mathbf{1}(Y\geq t)\)&lt;/span&gt; is 1 when the answer is yes and 0 otherwise. Averaging these answers gives a probability. The conditional expectation &lt;span class=&#34;math inline&#34;&gt;\(E\{\mathbf{1}(Y\geq t)\mid X\}\)&lt;/span&gt;, also written &lt;span class=&#34;math inline&#34;&gt;\(P(Y\geq t\mid X)\)&lt;/span&gt;, is the chance of a yes answer when we know &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;. The vertical bar means “given that we know”.&lt;/p&gt;
&lt;p&gt;The top of the fraction measures how much this chance changes as &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; changes. Here &lt;span class=&#34;math inline&#34;&gt;\(\operatorname{Var}\)&lt;/span&gt; measures that spread. The bottom measures the spread in the original yes or no answers, providing a reference for the comparison. The integral signs mean that we average each kind of spread across cutoffs, weighted according to the distribution of &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;, denoted by &lt;span class=&#34;math inline&#34;&gt;\(F_Y\)&lt;/span&gt;. The fraction compares these two averages, describing how much variation in the cutoff questions is explained by knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The population coefficient lies between zero and one. Under independence, knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; does not change the chance of a yes answer, so &lt;span class=&#34;math inline&#34;&gt;\(P(Y\geq t\mid X)=P(Y\geq t)\)&lt;/span&gt;. The top of the fraction is zero and &lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)=0\)&lt;/span&gt;. At the other extreme, if &lt;span class=&#34;math inline&#34;&gt;\(Y=f(X)\)&lt;/span&gt; almost surely for a measurable &lt;span class=&#34;math inline&#34;&gt;\(f\)&lt;/span&gt;, then knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; fixes &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; and settles every cutoff question. “Almost surely” means with probability one. The top and bottom are then equal, giving &lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)=1\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Reversing the order changes the question. When &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; is also nondegenerate, &lt;span class=&#34;math inline&#34;&gt;\(\xi(Y,X)\)&lt;/span&gt; uses knowledge of &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; to ask whether &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; passes different cutoffs. Its probabilities are &lt;span class=&#34;math inline&#34;&gt;\(P(X\geq t\mid Y)\)&lt;/span&gt;, averaged over the distribution of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;. Knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; to explain &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; and knowing &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; to explain &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; need not be equally informative in this sense.&lt;/p&gt;
&lt;p&gt;For the quadratic example without noise, &lt;span class=&#34;math inline&#34;&gt;\(Y=X^2\)&lt;/span&gt; is determined by &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;. In the reverse direction, &lt;span class=&#34;math inline&#34;&gt;\(X=\pm\sqrt{Y}\)&lt;/span&gt;, so knowledge of &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; leaves the sign unresolved. Thus &lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)=1\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(\xi(Y,X)&amp;lt;1\)&lt;/span&gt;. The exact reverse population value is unnecessary for this comparison.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;xi_y_given_x&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;xi_x_given_y&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;direction_confirmed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;0.999&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.269&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This validation uses a random continuous sample so the reverse calculation is not driven by exact ties in &lt;span class=&#34;math inline&#34;&gt;\(Y=X^2\)&lt;/span&gt;. It confirms the label used below. &lt;code&gt;xi(X, Y)&lt;/code&gt; means “Y given X” in this article.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/xi-plot-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;In practice, I would use &lt;span class=&#34;math inline&#34;&gt;\(\xi\)&lt;/span&gt; when it matters whether knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; helps explain &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; more than knowing &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; helps explain &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;. Threshold and saturation relationships, like the quadratic curve, can give the same response for several inputs.&lt;/p&gt;
&lt;p&gt;If the relationship is roughly linear or monotonic and the scientific question treats both variables equally, Pearson, Spearman or Kendall may already give a more interpretable summary. I would add &lt;span class=&#34;math inline&#34;&gt;\(\xi\)&lt;/span&gt; when the difference between the two orders matters, rather than calculate it automatically.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Population pattern&lt;/th&gt;
&lt;th&gt;Interpretation in the sense measured by &lt;span class=&#34;math inline&#34;&gt;\(\xi\)&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)\approx\xi(Y,X)\)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Similar dependence strength in both directions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)&amp;gt;\xi(Y,X)\)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Stronger directional dependence of &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; on &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; than of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; on &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)\)&lt;/span&gt; near zero&lt;/td&gt;
&lt;td&gt;Knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; explains little about the cutoff questions for &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)\)&lt;/span&gt; near one&lt;/td&gt;
&lt;td&gt;Knowing &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; explains most cutoff variation, without implying exact determinism&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The guide describes population patterns, not formal classification rules. Directional dependence is not evidence of causal direction. Nor does it describe signed association. &lt;span class=&#34;math inline&#34;&gt;\(\xi(X,Y)\)&lt;/span&gt; can differ from &lt;span class=&#34;math inline&#34;&gt;\(\xi(Y,X)\)&lt;/span&gt; without indicating whether &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; increases or decreases with &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\text{directionality}\neq\text{sign}\neq\text{causality}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The original finite sample statistic need not reach one even for an exact functional relationship. With continuous observations and no ties, its upper bound is &lt;span class=&#34;math inline&#34;&gt;\((n-2)/(n+1)\)&lt;/span&gt;, which approaches one as the sample grows (&lt;a href=&#34;https://doi.org/10.1007/s42519-024-00399-y&#34;&gt;Dalitz, Arning and Goebbels, 2024&lt;/a&gt;). It can also be negative in finite samples; that does not indicate decreasing association. The optional software rescaling is described under &lt;a href=&#34;#reproducibility&#34;&gt;Reproducibility&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Chatterjee’s original statistic can have low local power against some alternatives (&lt;a href=&#34;https://doi.org/10.1093/biomet/asab028&#34;&gt;Shi, Drton and Han, 2022&lt;/a&gt;). Modified rank statistics can improve this aspect when independence testing is the primary objective (&lt;a href=&#34;https://doi.org/10.1093/biomet/asac048&#34;&gt;Lin and Han, 2023&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The next examples hold the underlying regression mechanism fixed and change which observations enter the sample.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sensitivity-to-the-observed-sample&#34; class=&#34;section level1&#34; number=&#34;7&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;7&lt;/span&gt; Sensitivity to the observed sample&lt;/h1&gt;
&lt;div id=&#34;influential-observations&#34; class=&#34;section level2&#34; number=&#34;7.1&#34;&gt;
&lt;h2&gt;&lt;span class=&#34;header-section-number&#34;&gt;7.1&lt;/span&gt; Influential observations&lt;/h2&gt;
&lt;p&gt;We deliberately move 4% of observations from a positive linear relationship into positions with high leverage opposing the main trend. This adversarial contamination exposes the influence of a small subset of the sample.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/robustness-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/robustness-bars-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;scenario&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;pearson&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;bicor&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;pbcor&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;skipped&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Clean linear&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.856&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.855&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.844&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.867&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Outlier contaminated&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.020&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.719&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.665&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.866&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Here the robust methods are not automatic replacements for Pearson. They are sensitivity diagnostics. In &lt;code&gt;matrixCorr&lt;/code&gt;, the examples are biweight midcorrelation through &lt;code&gt;bicor()&lt;/code&gt;, percentage bend correlation through &lt;code&gt;pbcor()&lt;/code&gt; and skipped Pearson correlation through &lt;code&gt;skipped_corr()&lt;/code&gt;. These methods achieve robustness in different ways. Biweight midcorrelation downweights extreme observations, and percentage bend correlation limits their influence by bending standardised marginal deviations. Skipped correlation identifies multivariate outliers using an explicit outlier detection rule and then computes correlation on the retained observations (&lt;a href=&#34;https://doi.org/10.1080/0266476032000148821&#34;&gt;Wilcox, 2004&lt;/a&gt;; &lt;a href=&#34;https://doi.org/10.3389/fpsyg.2012.00606&#34;&gt;Pernet, Wilcox and Rousselet, 2013&lt;/a&gt;). These methods need not estimate the same population functional. The particular detection rule used here is documented under &lt;a href=&#34;#reproducibility&#34;&gt;Reproducibility&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If robust correlations disagree substantially with Pearson, the estimated association is sensitive to a small subset of observations. Those points might be measurement errors, data processing problems, or rare but scientifically meaningful cases. This sensitivity analysis does not by itself justify deleting them.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;range-restriction&#34; class=&#34;section level2&#34; number=&#34;7.2&#34;&gt;
&lt;h2&gt;&lt;span class=&#34;header-section-number&#34;&gt;7.2&lt;/span&gt; Range restriction&lt;/h2&gt;
&lt;p&gt;Contamination concerns particular observations; range restriction concerns sampling only part of the underlying range. Restricting &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; can alter correlation even when the regression mechanism remains unchanged (&lt;a href=&#34;https://doi.org/10.3102/10769986012003282&#34;&gt;Mendoza and Mumford, 1987&lt;/a&gt;). The following comparison retains observations from a narrow central range of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/range-restriction-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;scenario&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;pearson&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Full X range&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1200&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.833&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Restricted X range&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;349&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.439&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;marginal-and-partial-correlation&#34; class=&#34;section level1&#34; number=&#34;8&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;8&lt;/span&gt; Marginal and partial correlation&lt;/h1&gt;
&lt;p&gt;Now create a common cause structure.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
Z \sim N(0,1), \qquad X = aZ+\varepsilon_X, \qquad Y=bZ+\varepsilon_Y.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The errors are independent centred Gaussian variables, also independent of &lt;span class=&#34;math inline&#34;&gt;\(Z\)&lt;/span&gt;. There is no direct term between &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;. Marginally, they move together because both move with &lt;span class=&#34;math inline&#34;&gt;\(Z\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://prof-thiagooliveira.netlify.app/post/beyond-pearson-correlation/index_files/figure-html/partial-1.png&#34; alt=&#34;&#34; width=&#34;1440&#34; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;scenario&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;marginal_pearson&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;partial_xy_given_z&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Common cause only&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.661&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.03&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Conventional partial correlation asks whether residual linear association remains after linearly adjusting for one or more variables. With one adjustment variable &lt;span class=&#34;math inline&#34;&gt;\(Z\)&lt;/span&gt;, the population partial correlation can be written as&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho_{XY\cdot Z}
=
\frac{
\rho_{XY}-\rho_{XZ}\rho_{YZ}
}{
\sqrt{(1-\rho_{XZ}^{2})(1-\rho_{YZ}^{2})}
}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In general,&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
\rho_{XY\cdot Z}=0
\not\Rightarrow
X \perp Y \mid Z.
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For jointly multivariate Gaussian variables with a nonsingular covariance matrix, zero partial correlation between two variables conditional on the remaining variables is equivalent to conditional independence (&lt;a href=&#34;https://doi.org/10.1111/j.1467-842X.2004.00360.x&#34;&gt;Baba, Shibata and Sibuya, 2004&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;We know &lt;span class=&#34;math inline&#34;&gt;\(Z\)&lt;/span&gt; is a common cause here because we constructed the mechanism. Partial correlation does not discover causal structure or establish that an adjustment set is appropriate. That requires assumptions about how the variables were generated.&lt;/p&gt;
&lt;details class=&#34;article-note&#34;&gt;
&lt;summary&gt;
Conditioning on a collider
&lt;/summary&gt;
&lt;div class=&#34;article-note-body&#34;&gt;
&lt;p&gt;Adjustment is not automatically beneficial. A collider has the structure&lt;/p&gt;
&lt;pre class=&#34;text&#34;&gt;&lt;code&gt;X -&amp;gt; Z &amp;lt;- Y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Conditioning on a collider can create an association between &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt; even when they were marginally independent (&lt;a href=&#34;https://doi.org/10.1097/00001648-199901000-00008&#34;&gt;Greenland, Pearl and Robins, 1999&lt;/a&gt;). The small simulation below uses independent &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(Y\)&lt;/span&gt;, then constructs &lt;span class=&#34;math inline&#34;&gt;\(Z\)&lt;/span&gt; from both.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;scenario&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;marginal_pearson&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;partial_xy_given_z&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Collider adjustment&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.027&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.568&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;“Adjusted” does not automatically mean “closer to the truth”.&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;final-remarks&#34; class=&#34;section level1&#34; number=&#34;9&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;9&lt;/span&gt; Final remarks&lt;/h1&gt;
&lt;p&gt;The measures considered here target different features of the joint distribution. Pearson describes linear association, Spearman and Kendall describe ordering, and distance correlation and HSIC address broader dependence. Chatterjee’s &lt;span class=&#34;math inline&#34;&gt;\(\xi\)&lt;/span&gt; adds directional dependence, robust estimators examine sensitivity to unusual observations, and partial correlation describes residual linear association after adjustment. They are not competing estimates of a common parameter, and their numerical magnitudes do not share a common interpretation.&lt;/p&gt;
&lt;p&gt;Agreement can be reassuring when the measures reflect compatible aspects of a relationship, but disagreement can also be informative. A small Pearson correlation accompanied by general dependence raises a different question from a discrepancy between Pearson and a robust estimator. The useful question is which feature of the joint distribution causes the disagreement, rather than which coefficient is numerically largest.&lt;/p&gt;
&lt;p&gt;A coefficient quantifies a selected feature, not the complete joint distribution. Curvature, heteroscedasticity, mixtures, influence and asymmetry can be lost in a single summary. Choosing a measure does not remove the need for scientific assumptions, uncertainty quantification and appropriate modelling.&lt;/p&gt;
&lt;p&gt;Describing dependence and making an inferential statement about it are different tasks. A sample coefficient estimates a population quantity, while evidence against independence requires an appropriate sampling or null distribution. Conventional distance correlation and biased empirical HSIC are especially useful reminders of this distinction because their sample values need not be zero under independence (&lt;a href=&#34;https://doi.org/10.1214/009053607000000505&#34;&gt;Székely, Rizzo and Bakirov, 2007&lt;/a&gt;; &lt;a href=&#34;https://proceedings.neurips.cc/paper/2007/file/d5cfead94f5350c12c322b5b664544c1-Paper.pdf&#34;&gt;Gretton et al., 2007&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The measure should therefore follow the scientific question. If linear association is the target, Pearson may be exactly the right statistic. Add another measure when it addresses a feature left unresolved by that analysis. There is no requirement to calculate every available coefficient.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before asking “what is the correlation?”, ask “what aspect of this relationship do I want to quantify?”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;references&#34; class=&#34;section level1&#34; number=&#34;10&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;10&lt;/span&gt; References&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Pearson, K. (1896). &lt;a href=&#34;https://doi.org/10.1098/rsta.1896.0007&#34;&gt;Mathematical Contributions to the Theory of Evolution. III. Regression, Heredity, and Panmixia&lt;/a&gt;. &lt;em&gt;Philosophical Transactions of the Royal Society of London. Series A&lt;/em&gt;, 187, 253 to 318.&lt;/li&gt;
&lt;li&gt;Spearman, C. (1904). &lt;a href=&#34;https://doi.org/10.2307/1412159&#34;&gt;The Proof and Measurement of Association between Two Things&lt;/a&gt;. &lt;em&gt;The American Journal of Psychology&lt;/em&gt;, 15(1), 72 to 101.&lt;/li&gt;
&lt;li&gt;Kendall, M. G. (1938). &lt;a href=&#34;https://doi.org/10.1093/biomet/30.1-2.81&#34;&gt;A New Measure of Rank Correlation&lt;/a&gt;. &lt;em&gt;Biometrika&lt;/em&gt;, 30(1 to 2), 81 to 93.&lt;/li&gt;
&lt;li&gt;Székely, G. J., Rizzo, M. L. and Bakirov, N. K. (2007). &lt;a href=&#34;https://projecteuclid.org/journals/annals-of-statistics/volume-35/issue-6/Measuring-and-testing-dependence-by-correlation-of-distances/10.1214/009053607000000505.full&#34;&gt;Measuring and Testing Dependence by Correlation of Distances&lt;/a&gt;. &lt;em&gt;The Annals of Statistics&lt;/em&gt;, 35(6), 2769 to 2794.&lt;/li&gt;
&lt;li&gt;Gretton, A., Bousquet, O., Smola, A. and Schölkopf, B. (2005). &lt;a href=&#34;https://www.cs.cmu.edu/~arthurg/papers/GreBouSmoSch05.pdf&#34;&gt;Measuring Statistical Dependence with Hilbert-Schmidt Norms&lt;/a&gt;. &lt;em&gt;Algorithmic Learning Theory&lt;/em&gt;, Lecture Notes in Computer Science 3734, 63 to 77.&lt;/li&gt;
&lt;li&gt;Gretton, A., Fukumizu, K., Teo, C. H., Song, L., Schölkopf, B. and Smola, A. (2007). &lt;a href=&#34;https://proceedings.neurips.cc/paper/2007/file/d5cfead94f5350c12c322b5b664544c1-Paper.pdf&#34;&gt;A Kernel Statistical Test of Independence&lt;/a&gt;. &lt;em&gt;Advances in Neural Information Processing Systems&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Dette, H., Siburg, K. F. and Stoimenov, P. A. (2013). &lt;a href=&#34;https://doi.org/10.1111/j.1467-9469.2011.00767.x&#34;&gt;A Copula-Based Non-parametric Measure of Regression Dependence&lt;/a&gt;. &lt;em&gt;Scandinavian Journal of Statistics&lt;/em&gt;, 40(1), 21 to 41.&lt;/li&gt;
&lt;li&gt;Chatterjee, S. (2021). &lt;a href=&#34;https://doi.org/10.1080/01621459.2020.1758115&#34;&gt;A New Coefficient of Correlation&lt;/a&gt;. &lt;em&gt;Journal of the American Statistical Association&lt;/em&gt;, 116(536), 2009 to 2022.&lt;/li&gt;
&lt;li&gt;Shi, H., Drton, M. and Han, F. (2022). &lt;a href=&#34;https://doi.org/10.1093/biomet/asab028&#34;&gt;On the Power of Chatterjee’s Rank Correlation&lt;/a&gt;. &lt;em&gt;Biometrika&lt;/em&gt;, 109(2), 317 to 333.&lt;/li&gt;
&lt;li&gt;Lin, Z. and Han, F. (2023). &lt;a href=&#34;https://doi.org/10.1093/biomet/asac048&#34;&gt;On Boosting the Power of Chatterjee’s Rank Correlation&lt;/a&gt;. &lt;em&gt;Biometrika&lt;/em&gt;, 110(2), 283 to 299.&lt;/li&gt;
&lt;li&gt;Lin, Z. and Han, F. (2025). &lt;a href=&#34;https://doi.org/10.48550/arXiv.2204.08031&#34;&gt;Limit Theorems of Chatterjee’s Rank Correlation&lt;/a&gt;. arXiv:2204.08031.&lt;/li&gt;
&lt;li&gt;Dette, H. and Kroll, M. (2025). &lt;a href=&#34;https://doi.org/10.1093/biomet/asae045&#34;&gt;A Simple Bootstrap for Chatterjee’s Rank Correlation&lt;/a&gt;. &lt;em&gt;Biometrika&lt;/em&gt;, 112(1), asae045.&lt;/li&gt;
&lt;li&gt;Dalitz, C., Arning, J. and Goebbels, S. (2024). &lt;a href=&#34;https://doi.org/10.1007/s42519-024-00399-y&#34;&gt;A Simple Bias Reduction for Chatterjee’s Correlation&lt;/a&gt;. &lt;em&gt;Journal of Statistical Theory and Practice&lt;/em&gt;, 18, Article 51.&lt;/li&gt;
&lt;li&gt;Pernet, C. R., Wilcox, R. and Rousselet, G. A. (2013). &lt;a href=&#34;https://doi.org/10.3389/fpsyg.2012.00606&#34;&gt;Robust Correlation Analyses: False Positive and Power Validation Using a New Open Source Matlab Toolbox&lt;/a&gt;. &lt;em&gt;Frontiers in Psychology&lt;/em&gt;, 3, Article 606.&lt;/li&gt;
&lt;li&gt;Baba, K., Shibata, R. and Sibuya, M. (2004). &lt;a href=&#34;https://doi.org/10.1111/j.1467-842X.2004.00360.x&#34;&gt;Partial Correlation and Conditional Correlation as Measures of Conditional Independence&lt;/a&gt;. &lt;em&gt;Australian and New Zealand Journal of Statistics&lt;/em&gt;, 46(4), 657 to 664.&lt;/li&gt;
&lt;li&gt;de Winter, J. C. F., Gosling, S. D. and Potter, J. (2016). &lt;a href=&#34;https://doi.org/10.1037/met0000079&#34;&gt;Comparing the Pearson and Spearman Correlation Coefficients Across Distributions and Sample Sizes: A Tutorial Using Simulations and Empirical Data&lt;/a&gt;. &lt;em&gt;Psychological Methods&lt;/em&gt;, 21(3), 273 to 290.&lt;/li&gt;
&lt;li&gt;Gretton, A., Herbrich, R., Smola, A., Bousquet, O. and Schölkopf, B. (2005). &lt;a href=&#34;https://jmlr.org/papers/v6/gretton05a.html&#34;&gt;Kernel Methods for Measuring Independence&lt;/a&gt;. &lt;em&gt;Journal of Machine Learning Research&lt;/em&gt;, 6, 2075 to 2129.&lt;/li&gt;
&lt;li&gt;Sriperumbudur, B. K., Gretton, A., Fukumizu, K., Schölkopf, B. and Lanckriet, G. R. G. (2010). &lt;a href=&#34;https://jmlr.org/papers/v11/sriperumbudur10a.html&#34;&gt;Hilbert Space Embeddings and Metrics on Probability Measures&lt;/a&gt;. &lt;em&gt;Journal of Machine Learning Research&lt;/em&gt;, 11, 1517 to 1561.&lt;/li&gt;
&lt;li&gt;Mendoza, J. L. and Mumford, M. (1987). &lt;a href=&#34;https://doi.org/10.3102/10769986012003282&#34;&gt;Corrections for Attenuation and Range Restriction on the Predictor&lt;/a&gt;. &lt;em&gt;Journal of Educational Statistics&lt;/em&gt;, 12(3), 282 to 293.&lt;/li&gt;
&lt;li&gt;Wilcox, R. R. (2004). &lt;a href=&#34;https://doi.org/10.1080/0266476032000148821&#34;&gt;Inferences Based on a Skipped Correlation Coefficient&lt;/a&gt;. &lt;em&gt;Journal of Applied Statistics&lt;/em&gt;, 31(2), 131 to 143.&lt;/li&gt;
&lt;li&gt;Greenland, S., Pearl, J. and Robins, J. M. (1999). &lt;a href=&#34;https://doi.org/10.1097/00001648-199901000-00008&#34;&gt;Causal Diagrams for Epidemiologic Research&lt;/a&gt;. &lt;em&gt;Epidemiology&lt;/em&gt;, 10(1), 37 to 48.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;reproducibility&#34; class=&#34;section level1&#34; number=&#34;11&#34;&gt;
&lt;h1&gt;&lt;span class=&#34;header-section-number&#34;&gt;11&lt;/span&gt; Reproducibility&lt;/h1&gt;
&lt;p&gt;The package behaviour was verified against &lt;a href=&#34;https://github.com/Prof-ThiagoOliveira/matrixCorr/tree/1811a8cfbedffde8d81d5b683b591d568dde2bc5&#34;&gt;the current &lt;code&gt;matrixCorr&lt;/code&gt; GitHub implementation&lt;/a&gt;, version 0.12.3. The figures and tables in this article use that implementation. The following are software conventions, separate from the population results cited above.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;matrixCorr::dcor()&lt;/code&gt; returns the conventional nonnegative sample distance correlation &lt;span class=&#34;math inline&#34;&gt;\(R_n\)&lt;/span&gt; from doubly centred distance matrices. &lt;code&gt;dcor(squared = TRUE)&lt;/code&gt; returns &lt;span class=&#34;math inline&#34;&gt;\(R_n^2\)&lt;/span&gt;. The separate &lt;code&gt;bcdcor()&lt;/code&gt; function returns the signed, U centred bias corrected squared distance correlation statistic, which can be negative in finite samples.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;matrixCorr::dcor(p_value = TRUE)&lt;/code&gt; reports conventional distance correlation in the displayed matrix, while the attached independence test metadata use the signed bias corrected statistic returned by &lt;code&gt;bcdcor()&lt;/code&gt;. The attached t test is not computed directly from the displayed &lt;span class=&#34;math inline&#34;&gt;\(R_n\)&lt;/span&gt;. &lt;code&gt;matrixCorr::hsic(p_value = TRUE)&lt;/code&gt; can attach permutation p values; this article uses its normalised biased estimator with Gaussian kernels and median bandwidths.&lt;/p&gt;
&lt;p&gt;The default &lt;code&gt;xi_corr()&lt;/code&gt; returns the original finite sample statistic. &lt;code&gt;bias_correction = &#34;upper_bound&#34;&lt;/code&gt; divides it by its finite sample upper bound, leaving the population target unchanged. For skipped Pearson correlation, this implementation uses a projection based bivariate outlier rule for each variable pair, then computes Pearson correlation on the retained observations.&lt;/p&gt;
&lt;p&gt;The main text hides R chunks so the statistical narrative stays readable. Open the panel below to inspect the reusable simulation and plotting code.&lt;/p&gt;
&lt;details class=&#34;article-note&#34;&gt;
&lt;summary&gt;
Reusable R code
&lt;/summary&gt;
&lt;div class=&#34;article-note-body&#34;&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Reusable simulations and plotting helpers for the &amp;quot;Beyond Pearson&amp;quot; post.

BEYOND_PEARSON &amp;lt;- list(
  seed = 20260927L,
  n = 500L,
  rho_linear = 0.70,
  monotonic_a = 0.85,
  monotonic_noise = 0.45,
  quadratic_noise = 0.35,
  periodic_noise = 0.35,
  outlier_n = 400L,
  outlier_fraction = 0.04,
  outlier_noise = 0.45,
  opening_outlier_scale = 0.77,
  range_n = 1200L,
  range_restriction = 0.55,
  confound_a = 0.85,
  confound_b = 0.80,
  confound_noise = 0.55,
  confound_direct = 0.25,
  collider_a = 0.80,
  collider_b = 0.80,
  collider_noise = 0.65
)

required_packages &amp;lt;- function() {
  required &amp;lt;- c(&amp;quot;matrixCorr&amp;quot;, &amp;quot;ggplot2&amp;quot;, &amp;quot;knitr&amp;quot;)
  missing &amp;lt;- required[!vapply(required, requireNamespace, logical(1), quietly = TRUE)]
  if (length(missing) &amp;gt; 0L) {
    stop(&amp;quot;Install required packages: &amp;quot;, paste(missing, collapse = &amp;quot;, &amp;quot;), call. = FALSE)
  }
  if (!&amp;quot;bcdcor&amp;quot; %in% getNamespaceExports(&amp;quot;matrixCorr&amp;quot;) ||
      !&amp;quot;squared&amp;quot; %in% names(formals(matrixCorr::dcor))) {
    stop(paste(
      &amp;quot;Install the current GitHub matrixCorr implementation with conventional dcor() and bcdcor().&amp;quot;,
      &amp;quot;Follow the project .Rlib installation instructions in the post README and restart R if matrixCorr is already loaded.&amp;quot;
    ),
         call. = FALSE)
  }
  invisible(TRUE)
}

simulate_relationship &amp;lt;- function(type,
                                  n = BEYOND_PEARSON$n,
                                  seed = BEYOND_PEARSON$seed,
                                  noise = NULL,
                                  rho = BEYOND_PEARSON$rho_linear) {
  type &amp;lt;- match.arg(
    type,
    c(
      &amp;quot;independent&amp;quot;, &amp;quot;linear&amp;quot;, &amp;quot;monotonic&amp;quot;, &amp;quot;quadratic&amp;quot;, &amp;quot;periodic&amp;quot;,
      &amp;quot;outlier_clean&amp;quot;, &amp;quot;outlier_contaminated&amp;quot;,
      &amp;quot;confounded&amp;quot;, &amp;quot;confounded_direct&amp;quot;, &amp;quot;collider&amp;quot;,
      &amp;quot;range_full&amp;quot;, &amp;quot;range_restricted&amp;quot;,
      &amp;quot;opening_linear&amp;quot;, &amp;quot;opening_curved&amp;quot;, &amp;quot;opening_outliers&amp;quot;,
      &amp;quot;opening_heteroscedastic&amp;quot;, &amp;quot;opening_mixture&amp;quot;
    )
  )
  set.seed(seed)

  if (type == &amp;quot;independent&amp;quot;) {
    x &amp;lt;- rnorm(n)
    y &amp;lt;- rnorm(n)
    return(data.frame(scenario = &amp;quot;Independent Gaussian&amp;quot;, x = x, y = y))
  }

  if (type == &amp;quot;linear&amp;quot;) {
    x &amp;lt;- rnorm(n)
    eps &amp;lt;- rnorm(n)
    y &amp;lt;- rho * x + sqrt(1 - rho^2) * eps
    return(data.frame(scenario = &amp;quot;Linear Gaussian&amp;quot;, x = x, y = y))
  }

  if (type == &amp;quot;monotonic&amp;quot;) {
    sigma &amp;lt;- noise %||% BEYOND_PEARSON$monotonic_noise
    x &amp;lt;- rnorm(n)
    y &amp;lt;- exp(BEYOND_PEARSON$monotonic_a * x) + rnorm(n, sd = sigma)
    return(data.frame(scenario = &amp;quot;Monotonic nonlinear&amp;quot;, x = x, y = y))
  }

  if (type == &amp;quot;quadratic&amp;quot;) {
    sigma &amp;lt;- noise %||% BEYOND_PEARSON$quadratic_noise
    x &amp;lt;- rnorm(n)
    y &amp;lt;- x^2 + rnorm(n, sd = sigma)
    return(data.frame(scenario = &amp;quot;Quadratic&amp;quot;, x = x, y = y))
  }

  if (type == &amp;quot;periodic&amp;quot;) {
    sigma &amp;lt;- noise %||% BEYOND_PEARSON$periodic_noise
    x &amp;lt;- runif(n, -pi, pi)
    y &amp;lt;- sin(2 * x) + rnorm(n, sd = sigma)
    return(data.frame(scenario = &amp;quot;Periodic&amp;quot;, x = x, y = y))
  }

  if (type %in% c(&amp;quot;outlier_clean&amp;quot;, &amp;quot;outlier_contaminated&amp;quot;)) {
    n &amp;lt;- BEYOND_PEARSON$outlier_n
    x &amp;lt;- rnorm(n)
    y &amp;lt;- 0.8 * x + rnorm(n, sd = BEYOND_PEARSON$outlier_noise)
    contaminated &amp;lt;- rep(FALSE, n)
    if (type == &amp;quot;outlier_contaminated&amp;quot;) {
      m &amp;lt;- max(1L, round(BEYOND_PEARSON$outlier_fraction * n))
      idx &amp;lt;- sample(seq_len(n), m)
      contaminated[idx] &amp;lt;- TRUE
      x[idx] &amp;lt;- x[idx] + runif(m, 3.5, 5.0)
      y[idx] &amp;lt;- y[idx] - runif(m, 3.5, 5.0)
    }
    label &amp;lt;- if (type == &amp;quot;outlier_clean&amp;quot;) &amp;quot;Clean linear&amp;quot; else &amp;quot;Outlier contaminated&amp;quot;
    return(data.frame(scenario = label, x = x, y = y, contaminated = contaminated))
  }

  if (type %in% c(&amp;quot;confounded&amp;quot;, &amp;quot;confounded_direct&amp;quot;)) {
    z &amp;lt;- rnorm(n)
    x &amp;lt;- BEYOND_PEARSON$confound_a * z + rnorm(n, sd = BEYOND_PEARSON$confound_noise)
    direct &amp;lt;- if (type == &amp;quot;confounded_direct&amp;quot;) BEYOND_PEARSON$confound_direct else 0
    y &amp;lt;- BEYOND_PEARSON$confound_b * z + direct * x + rnorm(n, sd = BEYOND_PEARSON$confound_noise)
    label &amp;lt;- if (type == &amp;quot;confounded&amp;quot;) &amp;quot;Common cause only&amp;quot; else &amp;quot;Common cause plus direct association&amp;quot;
    return(data.frame(scenario = label, x = x, y = y, z = z))
  }

  if (type == &amp;quot;collider&amp;quot;) {
    x &amp;lt;- rnorm(n)
    y &amp;lt;- rnorm(n)
    z &amp;lt;- BEYOND_PEARSON$collider_a * x + BEYOND_PEARSON$collider_b * y +
      rnorm(n, sd = BEYOND_PEARSON$collider_noise)
    return(data.frame(scenario = &amp;quot;Collider adjustment&amp;quot;, x = x, y = y, z = z))
  }

  if (type %in% c(&amp;quot;range_full&amp;quot;, &amp;quot;range_restricted&amp;quot;)) {
    n_full &amp;lt;- max(n, BEYOND_PEARSON$range_n)
    x_full &amp;lt;- runif(n_full, -2, 2)
    y_full &amp;lt;- 0.75 * x_full + rnorm(n_full, sd = 0.55)
    if (type == &amp;quot;range_restricted&amp;quot;) {
      keep &amp;lt;- abs(x_full) &amp;lt;= BEYOND_PEARSON$range_restriction
      x_full &amp;lt;- x_full[keep]
      y_full &amp;lt;- y_full[keep]
      label &amp;lt;- &amp;quot;Restricted X range&amp;quot;
    } else {
      label &amp;lt;- &amp;quot;Full X range&amp;quot;
    }
    return(data.frame(scenario = label, x = x_full, y = y_full))
  }

  if (type == &amp;quot;opening_linear&amp;quot;) {
    x &amp;lt;- rnorm(n)
    y &amp;lt;- 0.60 * x + sqrt(1 - 0.60^2) * rnorm(n)
    return(data.frame(scenario = &amp;quot;Gaussian linear&amp;quot;, x = x, y = y))
  }

  if (type == &amp;quot;opening_curved&amp;quot;) {
    x &amp;lt;- rnorm(n)
    y &amp;lt;- exp(0.65 * x) + rnorm(n, sd = 0.85)
    return(data.frame(scenario = &amp;quot;Curved monotonic&amp;quot;, x = x, y = y))
  }

  if (type == &amp;quot;opening_outliers&amp;quot;) {
    dat &amp;lt;- simulate_relationship(&amp;quot;outlier_clean&amp;quot;, seed = seed)
    # Spread isolated points across both sides of the cloud, with varied
    # offsets and equal numbers above and below the main trend.
    # The fixed scale gives r about 0.78 for the opening figure&amp;#39;s seed.
    m &amp;lt;- 2L * max(1L, round(BEYOND_PEARSON$outlier_fraction * nrow(dat) / 2L))
    idx &amp;lt;- sample(seq_len(nrow(dat)), m)
    dat$x[idx] &amp;lt;- seq(-6, 6, length.out = m) + runif(m, -0.25, 0.25)
    direction &amp;lt;- sample(rep(c(-1, 1), each = m / 2L))
    magnitude &amp;lt;- runif(m, 2, 5.5)
    dat$y[idx] &amp;lt;- 0.8 * dat$x[idx] +
      direction * magnitude * BEYOND_PEARSON$opening_outlier_scale
    dat$scenario &amp;lt;- &amp;quot;Influential observations&amp;quot;
    return(dat[, c(&amp;quot;scenario&amp;quot;, &amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;)])
  }

  if (type == &amp;quot;opening_heteroscedastic&amp;quot;) {
    x &amp;lt;- rnorm(n)
    y &amp;lt;- 0.62 * x + rnorm(n, sd = 0.25 + 0.55 * abs(x))
    return(data.frame(scenario = &amp;quot;Heteroscedastic&amp;quot;, x = x, y = y))
  }

  x &amp;lt;- c(rnorm(n / 2L, -1.2, 0.55), rnorm(n - n / 2L, 1.2, 0.55))
  y &amp;lt;- c(rnorm(n / 2L, -0.55, 0.45), rnorm(n - n / 2L, 0.95, 0.45))
  data.frame(scenario = &amp;quot;Two clusters&amp;quot;, x = x, y = y)
}

`%||%` &amp;lt;- function(x, y) {
  if (is.null(x)) y else x
}

pair_value &amp;lt;- function(object, x_name = &amp;quot;x&amp;quot;, y_name = &amp;quot;y&amp;quot;) {
  unname(as.matrix(object)[x_name, y_name])
}

safe_pair_value &amp;lt;- function(expr) {
  tryCatch(expr, error = function(e) NA_real_)
}

summarise_dependence &amp;lt;- function(x, y,
                                 include_robust = TRUE,
                                 hsic_normalise = TRUE,
                                 xi_bias_correction = &amp;quot;none&amp;quot;,
                                 xi_tie_method = &amp;quot;random&amp;quot;,
                                 xi_seed = BEYOND_PEARSON$seed + 9000L) {
  required_packages()
  xy &amp;lt;- cbind(x = x, y = y)
  out &amp;lt;- data.frame(
    n = length(x),
    pearson = safe_pair_value(pair_value(matrixCorr::pearson_corr(xy))),
    spearman = safe_pair_value(pair_value(matrixCorr::spearman_rho(xy))),
    kendall = safe_pair_value(pair_value(matrixCorr::kendall_tau(xy))),
    dcor = safe_pair_value(pair_value(matrixCorr::dcor(xy, squared = FALSE))),
    hsic = safe_pair_value(pair_value(matrixCorr::hsic(
      xy,
      kernel = &amp;quot;gaussian&amp;quot;,
      bandwidth = &amp;quot;median&amp;quot;,
      normalise = hsic_normalise,
      estimator = &amp;quot;biased&amp;quot;
    ))),
    xi_y_given_x = safe_pair_value(matrixCorr::xi_corr(
      x,
      y,
      tie_method = xi_tie_method,
      seed = xi_seed,
      bias_correction = xi_bias_correction
    )),
    xi_x_given_y = safe_pair_value(matrixCorr::xi_corr(
      y,
      x,
      tie_method = xi_tie_method,
      seed = xi_seed,
      bias_correction = xi_bias_correction
    ))
  )

  if (include_robust) {
    out$bicor &amp;lt;- safe_pair_value(pair_value(matrixCorr::bicor(xy)))
    out$pbcor &amp;lt;- safe_pair_value(pair_value(matrixCorr::pbcor(xy)))
    out$skipped &amp;lt;- safe_pair_value(pair_value(matrixCorr::skipped_corr(xy)))
  }

  out
}

main_scenarios &amp;lt;- function() {
  types &amp;lt;- c(&amp;quot;linear&amp;quot;, &amp;quot;monotonic&amp;quot;, &amp;quot;quadratic&amp;quot;, &amp;quot;periodic&amp;quot;)
  seeds &amp;lt;- BEYOND_PEARSON$seed + seq_along(types) - 1L
  stats::setNames(
    Map(simulate_relationship, types, seed = seeds),
    c(&amp;quot;Linear&amp;quot;, &amp;quot;Monotonic nonlinear&amp;quot;, &amp;quot;Quadratic&amp;quot;, &amp;quot;Periodic&amp;quot;)
  )
}

opening_scenarios &amp;lt;- function() {
  types &amp;lt;- c(
    &amp;quot;opening_linear&amp;quot;, &amp;quot;opening_curved&amp;quot;, &amp;quot;opening_outliers&amp;quot;,
    &amp;quot;opening_heteroscedastic&amp;quot;, &amp;quot;opening_mixture&amp;quot;
  )
  seeds &amp;lt;- BEYOND_PEARSON$seed + 100L + seq_along(types)
  stats::setNames(Map(simulate_relationship, types, seed = seeds), types)
}

summary_table &amp;lt;- function(scenarios) {
  rows &amp;lt;- lapply(scenarios, function(dat) {
    cbind(
      scenario = unique(dat$scenario)[1L],
      summarise_dependence(dat$x, dat$y)
    )
  })
  do.call(rbind, rows)
}

partial_summary &amp;lt;- function(dat) {
  xyz &amp;lt;- cbind(x = dat$x, y = dat$y, z = dat$z)
  data.frame(
    scenario = unique(dat$scenario)[1L],
    marginal_pearson = pair_value(matrixCorr::pearson_corr(xyz[, c(&amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;)])),
    partial_xy_given_z = pair_value(matrixCorr::pcorr(xyz, method = &amp;quot;sample&amp;quot;), &amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;)
  )
}

range_summary &amp;lt;- function(full, restricted) {
  data.frame(
    scenario = c(unique(full$scenario)[1L], unique(restricted$scenario)[1L]),
    n = c(nrow(full), nrow(restricted)),
    pearson = c(
      pair_value(matrixCorr::pearson_corr(cbind(x = full$x, y = full$y))),
      pair_value(matrixCorr::pearson_corr(cbind(x = restricted$x, y = restricted$y)))
    )
  )
}

format_stat &amp;lt;- function(x) {
  ifelse(is.na(x), &amp;quot;NA&amp;quot;, sprintf(&amp;quot;%.3f&amp;quot;, x))
}

round_numeric_df &amp;lt;- function(x, digits = 3L) {
  numeric_cols &amp;lt;- vapply(x, is.numeric, logical(1))
  x[numeric_cols] &amp;lt;- lapply(x[numeric_cols], round, digits = digits)
  x
}

plot_relationship &amp;lt;- function(dat, title = unique(dat$scenario)[1L]) {
  required_packages()
  stats &amp;lt;- summarise_dependence(dat$x, dat$y, include_robust = FALSE)
  subtitle &amp;lt;- paste(
    &amp;quot;Pearson r =&amp;quot;, format_stat(stats$pearson),
    &amp;quot;| Spearman rho =&amp;quot;, format_stat(stats$spearman),
    &amp;quot;| Kendall tau =&amp;quot;, format_stat(stats$kendall),
    &amp;quot;| dCor =&amp;quot;, format_stat(stats$dcor)
  )
  ggplot2::ggplot(dat, ggplot2::aes(x, y)) +
    ggplot2::geom_point(alpha = 0.68, size = 1.4, color = &amp;quot;#2f4858&amp;quot;) +
    ggplot2::geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE, linewidth = 0.75, color = &amp;quot;#d1495b&amp;quot;) +
    ggplot2::labs(title = title, subtitle = subtitle, x = &amp;quot;X&amp;quot;, y = &amp;quot;Y&amp;quot;) +
    ggplot2::theme_minimal(base_size = 12)
}

plot_shape_panels &amp;lt;- function(scenarios) {
  required_packages()
  dat &amp;lt;- do.call(rbind, scenarios)
  dat$scenario &amp;lt;- factor(
    dat$scenario,
    levels = c(&amp;quot;Linear Gaussian&amp;quot;, &amp;quot;Monotonic nonlinear&amp;quot;, &amp;quot;Quadratic&amp;quot;, &amp;quot;Periodic&amp;quot;)
  )
  stats &amp;lt;- summary_table(scenarios)
  labels &amp;lt;- setNames(
    paste0(stats$scenario, &amp;quot;\nPearson r = &amp;quot;, format_stat(stats$pearson),
           &amp;quot;, dCor = &amp;quot;, format_stat(stats$dcor)),
    stats$scenario
  )
  ggplot2::ggplot(dat, ggplot2::aes(x, y)) +
    ggplot2::geom_point(alpha = 0.62, size = 1.15, color = &amp;quot;#284b63&amp;quot;) +
    ggplot2::geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE, linewidth = 0.55, color = &amp;quot;#d1495b&amp;quot;) +
    ggplot2::facet_wrap(
      ggplot2::vars(scenario),
      scales = &amp;quot;free&amp;quot;,
      labeller = ggplot2::as_labeller(labels)
    ) +
    ggplot2::labs(x = &amp;quot;X&amp;quot;, y = &amp;quot;Y&amp;quot;) +
    ggplot2::theme_minimal(base_size = 11) +
    ggplot2::theme(strip.text = ggplot2::element_text(face = &amp;quot;bold&amp;quot;))
}

long_measure_table &amp;lt;- function(tab,
                               measures = c(
                                 &amp;quot;pearson&amp;quot;, &amp;quot;spearman&amp;quot;, &amp;quot;kendall&amp;quot;, &amp;quot;dcor&amp;quot;,
                                 &amp;quot;hsic&amp;quot;, &amp;quot;xi_y_given_x&amp;quot;, &amp;quot;xi_x_given_y&amp;quot;
                               )) {
  long &amp;lt;- do.call(rbind, lapply(measures, function(measure) {
    data.frame(
      scenario = tab$scenario,
      measure = measure,
      value = as.numeric(tab[[measure]])
    )
  }))
  labels &amp;lt;- c(
    pearson = &amp;quot;Pearson&amp;quot;,
    spearman = &amp;quot;Spearman&amp;quot;,
    kendall = &amp;quot;Kendall&amp;quot;,
    dcor = &amp;quot;Distance correlation&amp;quot;,
    hsic = &amp;quot;Normalised HSIC&amp;quot;,
    xi_y_given_x = &amp;quot;xi(X, Y) for Y given X&amp;quot;,
    xi_x_given_y = &amp;quot;xi(Y, X) for X given Y&amp;quot;,
    bicor = &amp;quot;Biweight midcorrelation&amp;quot;,
    pbcor = &amp;quot;Percentage bend&amp;quot;,
    skipped = &amp;quot;Skipped Pearson&amp;quot;
  )
  long$measure_label &amp;lt;- unname(labels[long$measure])
  long
}

plot_measure_small_multiples &amp;lt;- function(tab) {
  required_packages()
  long &amp;lt;- long_measure_table(tab)
  ggplot2::ggplot(long, ggplot2::aes(scenario, value, fill = scenario)) +
    ggplot2::geom_col(width = 0.72, show.legend = FALSE) +
    ggplot2::facet_wrap(ggplot2::vars(measure_label), scales = &amp;quot;free_y&amp;quot;) +
    ggplot2::coord_flip() +
    ggplot2::labs(
      x = NULL,
      y = &amp;quot;Estimated value&amp;quot;,
      caption = &amp;quot;Compare patterns within each measure.&amp;quot;
    ) +
    ggplot2::scale_fill_manual(values = c(&amp;quot;#2f4858&amp;quot;, &amp;quot;#688e26&amp;quot;, &amp;quot;#d1495b&amp;quot;, &amp;quot;#5b5f97&amp;quot;, &amp;quot;#7f7f7f&amp;quot;)) +
    ggplot2::theme_minimal(base_size = 11)
}

plot_pearson_dcor &amp;lt;- function(tab) {
  required_packages()
  long &amp;lt;- long_measure_table(tab, measures = c(&amp;quot;pearson&amp;quot;, &amp;quot;dcor&amp;quot;))
  ggplot2::ggplot(long, ggplot2::aes(scenario, value, fill = measure_label)) +
    ggplot2::geom_col(position = ggplot2::position_dodge(width = 0.72), width = 0.64) +
    ggplot2::coord_flip() +
    ggplot2::labs(
      x = NULL,
      y = &amp;quot;Estimated value&amp;quot;,
      fill = NULL,
      caption = &amp;quot;Compare the quadratic scenario with the other simulated relationships.&amp;quot;
    ) +
    ggplot2::scale_fill_manual(values = c(&amp;quot;Distance correlation&amp;quot; = &amp;quot;#688e26&amp;quot;, &amp;quot;Pearson&amp;quot; = &amp;quot;#d1495b&amp;quot;)) +
    ggplot2::theme_minimal(base_size = 12)
}

plot_xi_direction &amp;lt;- function(tab) {
  required_packages()
  long &amp;lt;- long_measure_table(tab, measures = c(&amp;quot;xi_y_given_x&amp;quot;, &amp;quot;xi_x_given_y&amp;quot;))
  ggplot2::ggplot(long, ggplot2::aes(scenario, value, fill = measure_label)) +
    ggplot2::geom_col(position = ggplot2::position_dodge(width = 0.72), width = 0.64) +
    ggplot2::coord_flip() +
    ggplot2::labs(
      x = NULL,
      y = &amp;quot;Chatterjee xi&amp;quot;,
      fill = NULL,
      caption = &amp;quot;Compare the two argument orders within each scenario.&amp;quot;
    ) +
    ggplot2::scale_fill_manual(values = c(
      &amp;quot;xi(X, Y) for Y given X&amp;quot; = &amp;quot;#284b63&amp;quot;,
      &amp;quot;xi(Y, X) for X given Y&amp;quot; = &amp;quot;#f4a261&amp;quot;
    )) +
    ggplot2::theme_minimal(base_size = 12)
}

plot_robustness &amp;lt;- function(clean, contaminated) {
  required_packages()
  dat &amp;lt;- rbind(clean, contaminated)
  dat$scenario &amp;lt;- factor(dat$scenario, levels = c(&amp;quot;Clean linear&amp;quot;, &amp;quot;Outlier contaminated&amp;quot;))
  robust &amp;lt;- rbind(
    cbind(scenario = &amp;quot;Clean linear&amp;quot;, summarise_dependence(clean$x, clean$y)),
    cbind(scenario = &amp;quot;Outlier contaminated&amp;quot;, summarise_dependence(contaminated$x, contaminated$y))
  )
  long &amp;lt;- long_measure_table(
    robust,
    measures = c(&amp;quot;pearson&amp;quot;, &amp;quot;bicor&amp;quot;, &amp;quot;pbcor&amp;quot;, &amp;quot;skipped&amp;quot;)
  )
  scatter &amp;lt;- ggplot2::ggplot(dat, ggplot2::aes(x, y)) +
    ggplot2::geom_point(
      ggplot2::aes(color = contaminated),
      alpha = 0.68,
      size = 1.2,
      show.legend = FALSE
    ) +
    ggplot2::geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE, linewidth = 0.6, color = &amp;quot;#d1495b&amp;quot;) +
    ggplot2::facet_wrap(ggplot2::vars(scenario), scales = &amp;quot;free&amp;quot;) +
    ggplot2::scale_color_manual(values = c(&amp;quot;FALSE&amp;quot; = &amp;quot;#284b63&amp;quot;, &amp;quot;TRUE&amp;quot; = &amp;quot;#f4a261&amp;quot;)) +
    ggplot2::labs(x = &amp;quot;X&amp;quot;, y = &amp;quot;Y&amp;quot;) +
    ggplot2::theme_minimal(base_size = 11)
  bars &amp;lt;- ggplot2::ggplot(long, ggplot2::aes(measure_label, value, fill = scenario)) +
    ggplot2::geom_col(position = ggplot2::position_dodge(width = 0.72), width = 0.64) +
    ggplot2::coord_flip() +
    ggplot2::labs(x = NULL, y = &amp;quot;Estimated association&amp;quot;, fill = NULL) +
    ggplot2::scale_fill_manual(values = c(&amp;quot;Clean linear&amp;quot; = &amp;quot;#284b63&amp;quot;, &amp;quot;Outlier contaminated&amp;quot; = &amp;quot;#d1495b&amp;quot;)) +
    ggplot2::theme_minimal(base_size = 11)
  list(scatter = scatter, bars = bars, table = robust)
}

plot_partial &amp;lt;- function(dat) {
  required_packages()
  ps &amp;lt;- partial_summary(dat)
  long &amp;lt;- data.frame(
    measure = c(&amp;quot;Marginal Pearson r(X,Y)&amp;quot;, &amp;quot;Partial r(X,Y | Z)&amp;quot;),
    value = c(ps$marginal_pearson, ps$partial_xy_given_z)
  )
  ggplot2::ggplot(long, ggplot2::aes(measure, value, fill = measure)) +
    ggplot2::geom_col(width = 0.62, show.legend = FALSE) +
    ggplot2::coord_flip() +
    ggplot2::geom_hline(yintercept = 0, linewidth = 0.4) +
    ggplot2::labs(x = NULL, y = &amp;quot;Correlation&amp;quot;) +
    ggplot2::scale_fill_manual(values = c(&amp;quot;#284b63&amp;quot;, &amp;quot;#d1495b&amp;quot;)) +
    ggplot2::theme_minimal(base_size = 12)
}

# Exact population conversions under a bivariate normal model.
gaussian_correlations &amp;lt;- function(value,
                                  from = c(&amp;quot;pearson&amp;quot;, &amp;quot;spearman&amp;quot;, &amp;quot;kendall&amp;quot;)) {
  from &amp;lt;- match.arg(from)
  if (!is.numeric(value) || length(value) == 0L ||
      any(!is.finite(value)) || any(abs(value) &amp;gt; 1)) {
    stop(&amp;quot;value must contain finite numeric correlations between -1 and 1.&amp;quot;,
         call. = FALSE)
  }
  rho &amp;lt;- switch(from,
    pearson = value,
    spearman = 2 * sin(pi * value / 6),
    kendall = sin(pi * value / 2)
  )
  # Preserve exact endpoints despite floating-point sine evaluation.
  rho[abs(value) == 1] &amp;lt;- sign(value[abs(value) == 1])
  # Gaussian population dCor squared, with rationalised square-root terms
  # to avoid cancellation near independence.
  dcor_squared &amp;lt;- (
    rho * (asin(rho) - asin(rho / 2)) +
      rho^2 * (1 / (2 + sqrt(4 - rho^2)) -
                 1 / (1 + sqrt(1 - rho^2)))
  ) / (1 + pi / 3 - sqrt(3))
  data.frame(
    pearson = rho,
    spearman = 6 / pi * asin(rho / 2),
    kendall = 2 / pi * asin(rho),
    dcor = sqrt(pmax(0, pmin(1, dcor_squared)))
  )
}


gaussian_special_case &amp;lt;- function(rhos = seq(-1, 1, by = 0.1),
                                  n = 2500L,
                                  seed = BEYOND_PEARSON$seed + 2000L) {
  rows &amp;lt;- lapply(seq_along(rhos), function(i) {
    rho &amp;lt;- rhos[i]
    dat &amp;lt;- simulate_relationship(&amp;quot;linear&amp;quot;, n = n, seed = seed + i, rho = rho)
    cbind(rho = rho, summarise_dependence(dat$x, dat$y, include_robust = FALSE))
  })
  out &amp;lt;- do.call(rbind, rows)
  out$scenario &amp;lt;- paste0(&amp;quot;rho = &amp;quot;, out$rho)
  out
}

plot_gaussian_special_case &amp;lt;- function(tab) {
  required_packages()
  tab$scenario &amp;lt;- sprintf(&amp;quot;rho = %.1f&amp;quot;, tab$rho)
  measures &amp;lt;- c(&amp;quot;pearson&amp;quot;, &amp;quot;spearman&amp;quot;, &amp;quot;kendall&amp;quot;, &amp;quot;dcor&amp;quot;)
  long &amp;lt;- long_measure_table(tab, measures = measures)
  long$rho &amp;lt;- rep(tab$rho, length(measures))
  # Evaluate the population formulas on a dense grid for smooth reference curves.
  theory_rhos &amp;lt;- seq(-1, 1, length.out = 501L)
  theory_tab &amp;lt;- gaussian_correlations(theory_rhos)
  theory_tab$scenario &amp;lt;- as.character(theory_rhos)
  theory &amp;lt;- long_measure_table(theory_tab, measures = measures)
  theory$rho &amp;lt;- rep(theory_rhos, length(measures))
  ggplot2::ggplot(long, ggplot2::aes(rho, value, color = measure_label)) +
    ggplot2::geom_line(
      data = theory,
      ggplot2::aes(rho, value, color = measure_label),
      linewidth = 0.8,
      linetype = &amp;quot;22&amp;quot;
    ) +
    ggplot2::geom_line(linewidth = 0.8) +
    ggplot2::geom_point(size = 1.7) +
    ggplot2::scale_color_manual(values = c(
      &amp;quot;Pearson&amp;quot; = &amp;quot;#00BA38&amp;quot;, &amp;quot;Spearman&amp;quot; = &amp;quot;#619CFF&amp;quot;,
      &amp;quot;Kendall&amp;quot; = &amp;quot;#F8766D&amp;quot;, &amp;quot;Distance correlation&amp;quot; = &amp;quot;#8844AA&amp;quot;
    )) +
    ggplot2::scale_x_continuous(breaks = seq(-1, 1, by = 0.5)) +
    ggplot2::scale_y_continuous(breaks = seq(-1, 1, by = 0.5)) +
    ggplot2::coord_cartesian(xlim = c(-1, 1), ylim = c(-1, 1)) +
    ggplot2::labs(
      x = &amp;quot;Population Pearson rho used to generate bivariate normal data&amp;quot;,
      y = &amp;quot;Correlation coefficient&amp;quot;,
      color = NULL,
      caption = &amp;quot;Solid lines are simulated estimates. Dashed lines are the Gaussian reference formulas.&amp;quot;
    ) +
    ggplot2::theme_minimal(base_size = 12)
}

plot_opening_same_pearson &amp;lt;- function(scenarios) {
  required_packages()
  dat &amp;lt;- do.call(rbind, scenarios)
  stats &amp;lt;- summary_table(scenarios)
  labels &amp;lt;- setNames(
    paste0(stats$scenario, &amp;quot;\nPearson r = &amp;quot;, format_stat(stats$pearson)),
    stats$scenario
  )
  ggplot2::ggplot(dat, ggplot2::aes(x, y)) +
    ggplot2::geom_point(alpha = 0.62, size = 1.1, color = &amp;quot;#2f4858&amp;quot;) +
    ggplot2::geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE, linewidth = 0.55, color = &amp;quot;#d1495b&amp;quot;) +
    ggplot2::facet_wrap(
      ggplot2::vars(scenario),
      scales = &amp;quot;free&amp;quot;,
      labeller = ggplot2::as_labeller(labels)
    ) +
    ggplot2::labs(x = &amp;quot;X&amp;quot;, y = &amp;quot;Y&amp;quot;) +
    ggplot2::theme_minimal(base_size = 11) +
    ggplot2::theme(strip.text = ggplot2::element_text(face = &amp;quot;bold&amp;quot;))
}

monte_carlo_stability &amp;lt;- function(types = c(&amp;quot;independent&amp;quot;, &amp;quot;linear&amp;quot;, &amp;quot;quadratic&amp;quot;, &amp;quot;periodic&amp;quot;),
                                  reps = 200L,
                                  n = 300L,
                                  seed = BEYOND_PEARSON$seed + 5000L) {
  rows &amp;lt;- list()
  k &amp;lt;- 1L
  for (type in types) {
    for (r in seq_len(reps)) {
      dat &amp;lt;- simulate_relationship(type, n = n, seed = seed + 1000L * match(type, types) + r)
      stats &amp;lt;- summarise_dependence(dat$x, dat$y, include_robust = FALSE)
      rows[[k]] &amp;lt;- cbind(type = type, replicate = r, stats)
      k &amp;lt;- k + 1L
    }
  }
  do.call(rbind, rows)
}

monte_carlo_summary &amp;lt;- function(mc,
                                measures = c(&amp;quot;pearson&amp;quot;, &amp;quot;spearman&amp;quot;, &amp;quot;dcor&amp;quot;, &amp;quot;xi_y_given_x&amp;quot;)) {
  out &amp;lt;- do.call(rbind, lapply(split(mc, mc$type), function(dat) {
    do.call(rbind, lapply(measures, function(measure) {
      values &amp;lt;- as.numeric(dat[[measure]])
      data.frame(
        scenario = unique(dat$type),
        measure = measure,
        mean = mean(values, na.rm = TRUE),
        sd = stats::sd(values, na.rm = TRUE),
        q025 = unname(stats::quantile(values, 0.025, na.rm = TRUE)),
        median = stats::median(values, na.rm = TRUE),
        q975 = unname(stats::quantile(values, 0.975, na.rm = TRUE))
      )
    }))
  }))
  rownames(out) &amp;lt;- NULL
  out
}

validate_xi_direction &amp;lt;- function(n = 500L) {
  set.seed(BEYOND_PEARSON$seed + 7000L)
  x &amp;lt;- stats::runif(n, -1, 1)
  y &amp;lt;- x^2
  xi_y_given_x &amp;lt;- matrixCorr::xi_corr(x, y)
  xi_x_given_y &amp;lt;- matrixCorr::xi_corr(y, x)
  data.frame(
    xi_y_given_x = xi_y_given_x,
    xi_x_given_y = xi_x_given_y,
    direction_confirmed = xi_y_given_x &amp;gt; xi_x_given_y
  )
}

plot_range_restriction &amp;lt;- function(full, restricted) {
  required_packages()
  dat &amp;lt;- rbind(full, restricted)
  dat$scenario &amp;lt;- factor(dat$scenario, levels = c(&amp;quot;Full X range&amp;quot;, &amp;quot;Restricted X range&amp;quot;))
  stats &amp;lt;- range_summary(full, restricted)
  labels &amp;lt;- setNames(
    paste0(stats$scenario, &amp;quot;\nPearson r = &amp;quot;, format_stat(stats$pearson)),
    stats$scenario
  )
  ggplot2::ggplot(dat, ggplot2::aes(x, y)) +
    ggplot2::geom_point(alpha = 0.60, size = 1.05, color = &amp;quot;#284b63&amp;quot;) +
    ggplot2::geom_smooth(method = &amp;quot;lm&amp;quot;, se = FALSE, linewidth = 0.6, color = &amp;quot;#d1495b&amp;quot;) +
    ggplot2::facet_wrap(
      ggplot2::vars(scenario),
      scales = &amp;quot;free&amp;quot;,
      labeller = ggplot2::as_labeller(labels)
    ) +
    ggplot2::labs(x = &amp;quot;X&amp;quot;, y = &amp;quot;Y&amp;quot;) +
    ggplot2::theme_minimal(base_size = 11) +
    ggplot2::theme(strip.text = ggplot2::element_text(face = &amp;quot;bold&amp;quot;))
}

plot_workflow &amp;lt;- function() {
  required_packages()
  nodes &amp;lt;- data.frame(
    label = c(
      &amp;quot;Scientific question&amp;quot;,
      &amp;quot;Plot X against Y&amp;quot;,
      &amp;quot;Approximately linear?\nPearson&amp;quot;,
      &amp;quot;Ordered but curved?\nSpearman or Kendall&amp;quot;,
      &amp;quot;Nonmonotonic dependence?\ndCor or HSIC&amp;quot;,
      &amp;quot;Direction relevant?\nChatterjee xi&amp;quot;,
      &amp;quot;Influential observations?\nRobust sensitivity&amp;quot;,
      &amp;quot;Adjustment needed?\nPartial correlation or model&amp;quot;
    ),
    x = c(0, 0, -2.7, -1.35, 0, 1.35, 2.7, 0),
    y = c(3, 2, 0.75, 0.75, 0.75, 0.75, 0.75, -0.65)
  )
  edges &amp;lt;- data.frame(
    x = c(0, 0, 0, 0, 0, 0, 0),
    y = c(2.8, 1.8, 1.8, 1.8, 1.8, 1.8, 0.45),
    xend = c(0, -2.7, -1.35, 0, 1.35, 2.7, 0),
    yend = c(2.25, 1.05, 1.05, 1.05, 1.05, 1.05, -0.35)
  )
  ggplot2::ggplot() +
    ggplot2::geom_segment(
      data = edges,
      ggplot2::aes(x = x, y = y, xend = xend, yend = yend),
      linewidth = 0.45,
      color = &amp;quot;#6b7280&amp;quot;,
      arrow = ggplot2::arrow(length = grid::unit(0.12, &amp;quot;inches&amp;quot;))
    ) +
    ggplot2::geom_label(
      data = nodes,
      ggplot2::aes(x = x, y = y, label = label),
      label.size = 0.25,
      size = 3.2,
      fill = &amp;quot;#f8fafc&amp;quot;,
      color = &amp;quot;#111827&amp;quot;
    ) +
    ggplot2::coord_cartesian(xlim = c(-3.6, 3.6), ylim = c(-1.2, 3.4), expand = FALSE) +
    ggplot2::theme_void(base_size = 12)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;pre&gt;&lt;code&gt;## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=en_GB.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_GB.UTF-8        LC_COLLATE=en_GB.UTF-8    
##  [5] LC_MONETARY=en_GB.UTF-8    LC_MESSAGES=en_GB.UTF-8   
##  [7] LC_PAPER=en_GB.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Europe/London
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## loaded via a namespace (and not attached):
##  [1] Matrix_1.7-5       gtable_0.3.6       jsonlite_2.0.0     dplyr_1.2.1       
##  [5] compiler_4.6.1     tidyselect_1.2.1   Rcpp_1.1.1-1.1     dichromat_2.0-0.1 
##  [9] jquerylib_0.1.4    splines_4.6.1      scales_1.4.0       yaml_2.3.12       
## [13] fastmap_1.2.0      lattice_0.23-1     ggplot2_4.0.3      R6_2.6.1          
## [17] labeling_0.4.3     generics_0.1.4     matrixCorr_0.12.3  knitr_1.51        
## [21] tibble_3.3.1       bookdown_0.46      bslib_0.11.0       pillar_1.11.1     
## [25] RColorBrewer_1.1-3 rlang_1.2.0        cachem_1.1.0       xfun_0.58         
## [29] sass_0.4.10        S7_0.2.2           otel_0.2.0         cli_3.6.6         
## [33] mgcv_1.9-4         withr_3.0.2        magrittr_2.0.5     digest_0.6.39     
## [37] grid_4.6.1         rstudioapi_0.18.0  nlme_3.1-169       lifecycle_1.0.5   
## [41] vctrs_0.7.3        evaluate_1.0.5     glue_1.8.1         farver_2.1.2      
## [45] blogdown_1.24      rmarkdown_2.31     tools_4.6.1        pkgconfig_2.0.3   
## [49] htmltools_0.5.9&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
