Skip to content

Angular Correlation

aacorr(a, b, method='fl', test=False, strict=True)

Angular-Angular Correlation.

Parameters:

Name Type Description Default
a Union[Type[Circular], ndarray]

Angles in radian

required
b Union[Type[Circular], ndarray]

Angles in radian

required
method str
  • 'fl' (Fisher & Lee)
  • 'js' (Jammalamadaka & SenGupta)
  • 'nonparametric'
'fl'
test bool

Return significant test results.

False
strict bool

Strict mode. If True, raise an error when mean direction is not significant. Only for Jammalamadaka & SenGupta (2001)

True

Returns:

Name Type Description
r float

Correlation coefficient.

reject bool

Return significant test if test is set to True.

Source code in pycircstat2/correlation.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def aacorr(
    a: Union[Type[Circular], np.ndarray],
    b: Union[Type[Circular], np.ndarray],
    method: str = "fl",
    test: bool = False,
    strict: bool = True,
) -> tuple:
    """
    Angular-Angular Correlation.

    Parameters
    ----------
    a: Circular or np.ndarray
        Angles in radian
    b: Circular or np.ndarray
        Angles in radian
    method: str
        - 'fl' (Fisher & Lee)
        - 'js' (Jammalamadaka & SenGupta)
        - 'nonparametric'
    test: bool
        Return significant test results.
    strict: bool
        Strict mode. If True, raise an error when mean direction is
        not significant. Only for Jammalamadaka & SenGupta (2001)

    Returns
    -------
    r: float
        Correlation coefficient.
    reject: bool
        Return significant test if `test` is set to True.
    """

    if method == "fl":  # Fisher & Lee (1983)
        _corr = _aacorr_fl
    elif method == "js":  # Jammalamadaka & SenGupta (2001)
        _corr = _aacorr_js
    elif method == "nonparametric":
        _corr = _aacorr_np

    r = _corr(a, b, strict)

    if test:
        if isinstance(a, Circular):
            a = a.alpha
        if isinstance(b, Circular):
            b = b.alpha
        assert len(a) == len(b), "`a` and `b` must be the same length."

        if method == "nonparametric":
            # assuming α=0.05, critical values from P661, Zar, 2010
            n = len(a)
            reject = (n - 1) * r > 2.99 + 2.16 / n
        else:
            # jackknife test (Fingleton, 1989)
            n = len(a)
            raas = [
                _corr(np.delete(a, i), np.delete(b, i), strict)
                for i in range(n)
            ]
            m_raas = np.mean(raas)
            s2_raas = np.var(raas, ddof=1)
            z = norm.ppf(0.975)
            lb = n * r - (n - 1) * m_raas - z * np.sqrt(s2_raas / n)
            ub = n * r - (n - 1) * m_raas + z * np.sqrt(s2_raas / n)

            reject = ~(lb <= 0 <= ub)

        return r, reject
    else:
        return r

alcorr(a, x)

Angular-Linear Correlation based on Mardia (1972)

Parameters:

Name Type Description Default
a Union[Type[Circular], ndarray]

Angles in radian

required
x ndarray

Linear variable

required

Returns:

Name Type Description
ral float

correlation coefficient.

pval float
Reference

P658-659, Section 27.15(b) of Example 27.21 (Zar, 2010).

Source code in pycircstat2/correlation.py
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
def alcorr(
    a: Union[Type[Circular], np.ndarray],
    x: np.ndarray,
) -> float:
    """Angular-Linear Correlation based on Mardia (1972)

    Parameters
    ----------
    a: Circular or np.ndarray
        Angles in radian
    x: np.ndarray
        Linear variable

    Returns
    -------
    ral: float
        correlation coefficient.
    pval: float

    Reference
    ----
    P658-659, Section 27.15(b) of Example 27.21 (Zar, 2010).
    """

    if isinstance(a, Circular):
        a = a.alpha
    assert len(a) == len(x), "`a` and `x` must be the same length."

    n = len(a)

    rxc = np.corrcoef(np.cos(a), x)[0, 1]
    rxs = np.corrcoef(x, np.sin(a))[0, 1]
    rcs = np.corrcoef(np.sin(a), np.cos(a))[0, 1]

    num = rxc**2 + rxs**2 - 2 * rxc * rxs * rcs
    den = 1 - rcs**2
    ral = np.sqrt(num / den)

    pval = 1 - chi2(df=2).cdf(n * ral**2)

    return ral, pval