copulas 0.12.4.dev3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copulas/__init__.py +91 -0
- copulas/bivariate/__init__.py +175 -0
- copulas/bivariate/base.py +448 -0
- copulas/bivariate/clayton.py +163 -0
- copulas/bivariate/frank.py +170 -0
- copulas/bivariate/gumbel.py +144 -0
- copulas/bivariate/independence.py +81 -0
- copulas/bivariate/utils.py +19 -0
- copulas/datasets.py +214 -0
- copulas/errors.py +5 -0
- copulas/multivariate/__init__.py +8 -0
- copulas/multivariate/base.py +200 -0
- copulas/multivariate/gaussian.py +345 -0
- copulas/multivariate/tree.py +691 -0
- copulas/multivariate/vine.py +359 -0
- copulas/optimize/__init__.py +154 -0
- copulas/univariate/__init__.py +25 -0
- copulas/univariate/base.py +661 -0
- copulas/univariate/beta.py +48 -0
- copulas/univariate/gamma.py +38 -0
- copulas/univariate/gaussian.py +27 -0
- copulas/univariate/gaussian_kde.py +192 -0
- copulas/univariate/log_laplace.py +38 -0
- copulas/univariate/selection.py +36 -0
- copulas/univariate/student_t.py +31 -0
- copulas/univariate/truncated_gaussian.py +66 -0
- copulas/univariate/uniform.py +27 -0
- copulas/utils.py +248 -0
- copulas/visualization.py +345 -0
- copulas-0.12.4.dev3.dist-info/METADATA +215 -0
- copulas-0.12.4.dev3.dist-info/RECORD +34 -0
- copulas-0.12.4.dev3.dist-info/WHEEL +5 -0
- copulas-0.12.4.dev3.dist-info/licenses/LICENSE +106 -0
- copulas-0.12.4.dev3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""Clayton module."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from copulas.bivariate.base import Bivariate, CopulaTypes
|
|
6
|
+
from copulas.bivariate.utils import split_matrix
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Clayton(Bivariate):
|
|
10
|
+
"""Class for clayton copula model."""
|
|
11
|
+
|
|
12
|
+
copula_type = CopulaTypes.CLAYTON
|
|
13
|
+
theta_interval = [0, float('inf')]
|
|
14
|
+
invalid_thetas = []
|
|
15
|
+
|
|
16
|
+
def generator(self, t):
|
|
17
|
+
r"""Compute the generator function for Clayton copula family.
|
|
18
|
+
|
|
19
|
+
The generator is a function
|
|
20
|
+
:math:`\psi: [0,1]\times\Theta \rightarrow [0, \infty)` # noqa: JS101
|
|
21
|
+
|
|
22
|
+
that given an Archimedian copula fulfills:
|
|
23
|
+
.. math:: C(u,v) = \psi^{-1}(\psi(u) + \psi(v))
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
t (numpy.ndarray)
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
numpy.ndarray
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
self.check_fit()
|
|
33
|
+
|
|
34
|
+
return (1.0 / self.theta) * (np.power(t, -self.theta) - 1)
|
|
35
|
+
|
|
36
|
+
def probability_density(self, X):
|
|
37
|
+
r"""Compute probability density function for given copula family.
|
|
38
|
+
|
|
39
|
+
The probability density(PDF) for the Clayton family of copulas correspond to the formula:
|
|
40
|
+
|
|
41
|
+
.. math:: c(U,V) = \frac{\partial^2}{\partial v \partial u}C(u,v) =
|
|
42
|
+
(\theta + 1)(uv)^{-\theta-1}(u^{-\theta} +
|
|
43
|
+
v^{-\theta} - 1)^{-\frac{2\theta + 1}{\theta}}
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
X (numpy.ndarray)
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
numpy.ndarray: Probability density for the input values.
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
self.check_fit()
|
|
53
|
+
|
|
54
|
+
U, V = split_matrix(X)
|
|
55
|
+
|
|
56
|
+
a = (self.theta + 1) * np.power(U * V, -(self.theta + 1))
|
|
57
|
+
b = np.power(U, -self.theta) + np.power(V, -self.theta) - 1
|
|
58
|
+
c = -(2 * self.theta + 1) / self.theta
|
|
59
|
+
return a * np.power(b, c)
|
|
60
|
+
|
|
61
|
+
def cumulative_distribution(self, X):
|
|
62
|
+
"""Compute the cumulative distribution function for the clayton copula.
|
|
63
|
+
|
|
64
|
+
The cumulative density(cdf), or distribution function for the Clayton family of copulas
|
|
65
|
+
correspond to the formula:
|
|
66
|
+
|
|
67
|
+
.. math:: C(u,v) = (u^{-θ} + v^{-θ} - 1)^{-1/θ}
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
X (numpy.ndarray)
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
numpy.ndarray: cumulative probability.
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
self.check_fit()
|
|
77
|
+
|
|
78
|
+
U, V = split_matrix(X)
|
|
79
|
+
|
|
80
|
+
if (V == 0).all() or (U == 0).all():
|
|
81
|
+
return np.zeros(V.shape[0])
|
|
82
|
+
|
|
83
|
+
else:
|
|
84
|
+
cdfs = [
|
|
85
|
+
np.power(
|
|
86
|
+
np.power(U[i], -self.theta) + np.power(V[i], -self.theta) - 1,
|
|
87
|
+
-1.0 / self.theta,
|
|
88
|
+
)
|
|
89
|
+
if (U[i] > 0 and V[i] > 0)
|
|
90
|
+
else 0
|
|
91
|
+
for i in range(len(U))
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
return np.array(cdfs)
|
|
95
|
+
|
|
96
|
+
def percent_point(self, y, V):
|
|
97
|
+
"""Compute the inverse of conditional cumulative distribution :math:`C(u|v)^{-1}`.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
y (numpy.ndarray): Value of :math:`C(u|v)`.
|
|
101
|
+
v (numpy.ndarray): given value of v.
|
|
102
|
+
"""
|
|
103
|
+
self.check_fit()
|
|
104
|
+
|
|
105
|
+
if self.theta < 0:
|
|
106
|
+
return V
|
|
107
|
+
|
|
108
|
+
else:
|
|
109
|
+
a = np.power(y, self.theta / (-1 - self.theta))
|
|
110
|
+
b = np.power(V, self.theta)
|
|
111
|
+
|
|
112
|
+
# If b == 0, self.theta tends to inf,
|
|
113
|
+
# so the next operation tends to 1
|
|
114
|
+
if (b == 0).all():
|
|
115
|
+
return np.ones(len(V))
|
|
116
|
+
|
|
117
|
+
return np.power((a + b - 1) / b, -1 / self.theta)
|
|
118
|
+
|
|
119
|
+
def partial_derivative(self, X):
|
|
120
|
+
r"""Compute partial derivative of cumulative distribution.
|
|
121
|
+
|
|
122
|
+
The partial derivative of the copula(CDF) is the conditional CDF.
|
|
123
|
+
|
|
124
|
+
.. math:: F(v|u) = \frac{\partial C(u,v)}{\partial u} =
|
|
125
|
+
u^{- \theta - 1}(u^{-\theta} + v^{-\theta} - 1)^{-\frac{\theta+1}{\theta}}
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
X (np.ndarray)
|
|
129
|
+
y (float)
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
numpy.ndarray: Derivatives
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
self.check_fit()
|
|
136
|
+
|
|
137
|
+
U, V = split_matrix(X)
|
|
138
|
+
|
|
139
|
+
A = np.power(V, -self.theta - 1)
|
|
140
|
+
|
|
141
|
+
# If theta tends to inf, A tends to inf
|
|
142
|
+
# And the next partial_derivative tends to 0
|
|
143
|
+
if (A == np.inf).any():
|
|
144
|
+
return np.zeros(len(V))
|
|
145
|
+
|
|
146
|
+
B = np.power(V, -self.theta) + np.power(U, -self.theta) - 1
|
|
147
|
+
h = np.power(B, (-1 - self.theta) / self.theta)
|
|
148
|
+
return A * h
|
|
149
|
+
|
|
150
|
+
def compute_theta(self):
|
|
151
|
+
r"""Compute theta parameter using Kendall's tau.
|
|
152
|
+
|
|
153
|
+
On Clayton copula this is
|
|
154
|
+
|
|
155
|
+
.. math:: τ = θ/(θ + 2) \implies θ = 2τ/(1-τ)
|
|
156
|
+
.. math:: θ ∈ (0, ∞)
|
|
157
|
+
|
|
158
|
+
On the corner case of :math:`τ = 1`, return infinite.
|
|
159
|
+
"""
|
|
160
|
+
if self.tau == 1:
|
|
161
|
+
return np.inf
|
|
162
|
+
|
|
163
|
+
return 2 * self.tau / (1 - self.tau)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Frank module."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import scipy.integrate as integrate
|
|
7
|
+
from scipy.optimize import least_squares
|
|
8
|
+
|
|
9
|
+
from copulas.bivariate.base import Bivariate, CopulaTypes
|
|
10
|
+
from copulas.bivariate.utils import split_matrix
|
|
11
|
+
from copulas.utils import EPSILON
|
|
12
|
+
|
|
13
|
+
MIN_FLOAT_LOG = np.log(sys.float_info.min)
|
|
14
|
+
MAX_FLOAT_LOG = np.log(sys.float_info.max)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Frank(Bivariate):
|
|
18
|
+
"""Class for Frank copula model."""
|
|
19
|
+
|
|
20
|
+
copula_type = CopulaTypes.FRANK
|
|
21
|
+
theta_interval = [-float('inf'), float('inf')]
|
|
22
|
+
invalid_thetas = [0]
|
|
23
|
+
|
|
24
|
+
def generator(self, t):
|
|
25
|
+
"""Return the generator function."""
|
|
26
|
+
a = (np.exp(-self.theta * t) - 1) / (np.exp(-self.theta) - 1)
|
|
27
|
+
return -np.log(a)
|
|
28
|
+
|
|
29
|
+
def _g(self, z):
|
|
30
|
+
r"""Assist in solving the Frank copula.
|
|
31
|
+
|
|
32
|
+
This functions encapsulates :math:`g(z) = e^{-\theta z} - 1` used on Frank copulas.
|
|
33
|
+
|
|
34
|
+
Argument:
|
|
35
|
+
z: np.ndarray
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
np.ndarray
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
return np.exp(-self.theta * z) - 1
|
|
42
|
+
|
|
43
|
+
def probability_density(self, X):
|
|
44
|
+
r"""Compute probability density function for given copula family.
|
|
45
|
+
|
|
46
|
+
The probability density(PDF) for the Frank family of copulas correspond to the formula:
|
|
47
|
+
|
|
48
|
+
.. math:: c(U,V) = \frac{\partial^2 C(u,v)}{\partial v \partial u} =
|
|
49
|
+
\frac{-\theta g(1)(1 + g(u + v))}{(g(u) g(v) + g(1)) ^ 2}
|
|
50
|
+
|
|
51
|
+
Where the g function is defined by:
|
|
52
|
+
|
|
53
|
+
.. math:: g(x) = e^{-\theta x} - 1
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
X: `np.ndarray`
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
np.array: probability density
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
self.check_fit()
|
|
63
|
+
|
|
64
|
+
U, V = split_matrix(X)
|
|
65
|
+
|
|
66
|
+
if self.theta == 0:
|
|
67
|
+
return U * V
|
|
68
|
+
|
|
69
|
+
else:
|
|
70
|
+
num = (-self.theta * self._g(1)) * (1 + self._g(U + V))
|
|
71
|
+
aux = self._g(U) * self._g(V) + self._g(1)
|
|
72
|
+
den = np.power(aux, 2)
|
|
73
|
+
return num / den
|
|
74
|
+
|
|
75
|
+
def cumulative_distribution(self, X):
|
|
76
|
+
r"""Compute the cumulative distribution function for the Frank copula.
|
|
77
|
+
|
|
78
|
+
The cumulative density(cdf), or distribution function for the Frank family of copulas
|
|
79
|
+
correspond to the formula:
|
|
80
|
+
|
|
81
|
+
.. math:: C(u,v) = −\frac{\ln({\frac{1 + g(u) g(v)}{g(1)}})}{\theta}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
X: `np.ndarray`
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
np.array: cumulative distribution
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
self.check_fit()
|
|
92
|
+
|
|
93
|
+
U, V = split_matrix(X)
|
|
94
|
+
|
|
95
|
+
num = (np.exp(-self.theta * U) - 1) * (np.exp(-self.theta * V) - 1)
|
|
96
|
+
den = np.exp(-self.theta) - 1
|
|
97
|
+
|
|
98
|
+
return -1.0 / self.theta * np.log(1 + num / den)
|
|
99
|
+
|
|
100
|
+
def percent_point(self, y, V):
|
|
101
|
+
"""Compute the inverse of conditional cumulative distribution :math:`C(u|v)^{-1}`.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
y: `np.ndarray` value of :math:`C(u|v)`.
|
|
105
|
+
v: `np.ndarray` given value of v.
|
|
106
|
+
"""
|
|
107
|
+
self.check_fit()
|
|
108
|
+
|
|
109
|
+
if self.theta == 0:
|
|
110
|
+
return V
|
|
111
|
+
|
|
112
|
+
else:
|
|
113
|
+
return super().percent_point(y, V)
|
|
114
|
+
|
|
115
|
+
def partial_derivative(self, X):
|
|
116
|
+
r"""Compute partial derivative of cumulative distribution.
|
|
117
|
+
|
|
118
|
+
The partial derivative of the copula(CDF) is the conditional CDF.
|
|
119
|
+
|
|
120
|
+
.. math:: F(v|u) = \frac{\partial}{\partial u}C(u,v) =
|
|
121
|
+
\frac{g(u)g(v) + g(v)}{g(u)g(v) + g(1)}
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
X (np.ndarray)
|
|
125
|
+
y (float)
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
np.ndarray
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
self.check_fit()
|
|
132
|
+
|
|
133
|
+
U, V = split_matrix(X)
|
|
134
|
+
|
|
135
|
+
if self.theta == 0:
|
|
136
|
+
return V
|
|
137
|
+
|
|
138
|
+
else:
|
|
139
|
+
num = self._g(U) * self._g(V) + self._g(U)
|
|
140
|
+
den = self._g(U) * self._g(V) + self._g(1)
|
|
141
|
+
return num / den
|
|
142
|
+
|
|
143
|
+
def compute_theta(self):
|
|
144
|
+
r"""Compute theta parameter using Kendall's tau.
|
|
145
|
+
|
|
146
|
+
On Frank copula, the relationship between tau and theta is defined by:
|
|
147
|
+
|
|
148
|
+
.. math:: \tau = 1 − \frac{4}{\theta} + \frac{4}{\theta^2}\int_0^\theta \!
|
|
149
|
+
\frac{t}{e^t -1} \mathrm{d}t.
|
|
150
|
+
|
|
151
|
+
In order to solve it, we can simplify it as
|
|
152
|
+
|
|
153
|
+
.. math:: 0 = 1 + \frac{4}{\theta}(D_1(\theta) - 1) - \tau
|
|
154
|
+
|
|
155
|
+
where the function D is the Debye function of first order, defined as:
|
|
156
|
+
|
|
157
|
+
.. math:: D_1(x) = \frac{1}{x}\int_0^x\frac{t}{e^t -1} \mathrm{d}t.
|
|
158
|
+
|
|
159
|
+
"""
|
|
160
|
+
result = least_squares(self._tau_to_theta, 1, bounds=(MIN_FLOAT_LOG, MAX_FLOAT_LOG))
|
|
161
|
+
return result.x[0]
|
|
162
|
+
|
|
163
|
+
def _tau_to_theta(self, alpha):
|
|
164
|
+
"""Relationship between tau and theta as a solvable equation."""
|
|
165
|
+
|
|
166
|
+
def debye(t):
|
|
167
|
+
return t / (np.exp(t) - 1)
|
|
168
|
+
|
|
169
|
+
debye_value = integrate.quad(debye, EPSILON, alpha.item())[0] / alpha
|
|
170
|
+
return 4 * (debye_value - 1) / alpha + 1 - self.tau
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Gumbel module."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from copulas.bivariate.base import Bivariate, CopulaTypes
|
|
6
|
+
from copulas.bivariate.utils import split_matrix
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Gumbel(Bivariate):
|
|
10
|
+
"""Class for clayton copula model."""
|
|
11
|
+
|
|
12
|
+
copula_type = CopulaTypes.GUMBEL
|
|
13
|
+
theta_interval = [1, float('inf')]
|
|
14
|
+
invalid_thetas = []
|
|
15
|
+
|
|
16
|
+
def generator(self, t):
|
|
17
|
+
"""Return the generator function."""
|
|
18
|
+
return np.power(-np.log(t), self.theta)
|
|
19
|
+
|
|
20
|
+
def probability_density(self, X):
|
|
21
|
+
r"""Compute probability density function for given copula family.
|
|
22
|
+
|
|
23
|
+
The probability density(PDF) for the Gumbel family of copulas correspond to the formula:
|
|
24
|
+
|
|
25
|
+
.. math::
|
|
26
|
+
|
|
27
|
+
\begin{align}
|
|
28
|
+
c(U,V)
|
|
29
|
+
&= \frac{\partial^2 C(u,v)}{\partial v \partial u}
|
|
30
|
+
&= \frac{C(u,v)}{uv} \frac{((-\ln u)^{\theta} # noqa: JS101
|
|
31
|
+
+ (-\ln v)^{\theta})^{\frac{2} # noqa: JS101
|
|
32
|
+
{\theta} - 2 }}{(\ln u \ln v)^{1 - \theta}} # noqa: JS101
|
|
33
|
+
( 1 + (\theta-1) \big((-\ln u)^\theta
|
|
34
|
+
+ (-\ln v)^\theta\big)^{-1/\theta})
|
|
35
|
+
\end{align}
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
X (numpy.ndarray)
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
numpy.ndarray
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
self.check_fit()
|
|
45
|
+
|
|
46
|
+
U, V = split_matrix(X)
|
|
47
|
+
|
|
48
|
+
if self.theta == 1:
|
|
49
|
+
return U * V
|
|
50
|
+
|
|
51
|
+
else:
|
|
52
|
+
a = np.power(U * V, -1)
|
|
53
|
+
tmp = np.power(-np.log(U), self.theta) + np.power(-np.log(V), self.theta)
|
|
54
|
+
b = np.power(tmp, -2 + 2.0 / self.theta)
|
|
55
|
+
c = np.power(np.log(U) * np.log(V), self.theta - 1)
|
|
56
|
+
d = 1 + (self.theta - 1) * np.power(tmp, -1.0 / self.theta)
|
|
57
|
+
return self.cumulative_distribution(X) * a * b * c * d
|
|
58
|
+
|
|
59
|
+
def cumulative_distribution(self, X):
|
|
60
|
+
r"""Compute the cumulative distribution function for the Gumbel copula.
|
|
61
|
+
|
|
62
|
+
The cumulative density(cdf), or distribution function for the Gumbel family of copulas
|
|
63
|
+
correspond to the formula:
|
|
64
|
+
|
|
65
|
+
.. math:: C(u,v) = e^{-((-\ln u)^{\theta} + (-\ln v)^{\theta})^{\frac{1}{\theta}}}
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
X (np.ndarray)
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
np.ndarray: cumulative probability for the given datapoints, cdf(X).
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
self.check_fit()
|
|
75
|
+
|
|
76
|
+
U, V = split_matrix(X)
|
|
77
|
+
|
|
78
|
+
if self.theta == 1:
|
|
79
|
+
return U * V
|
|
80
|
+
|
|
81
|
+
else:
|
|
82
|
+
h = np.power(-np.log(U), self.theta) + np.power(-np.log(V), self.theta)
|
|
83
|
+
h = -np.power(h, 1.0 / self.theta)
|
|
84
|
+
cdfs = np.exp(h)
|
|
85
|
+
return cdfs
|
|
86
|
+
|
|
87
|
+
def percent_point(self, y, V):
|
|
88
|
+
"""Compute the inverse of conditional cumulative distribution :math:`C(u|v)^{-1}`.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
y (np.ndarray): value of :math:`C(u|v)`.
|
|
92
|
+
v (np.ndarray): given value of v.
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
self.check_fit()
|
|
96
|
+
|
|
97
|
+
if self.theta == 1:
|
|
98
|
+
return y
|
|
99
|
+
|
|
100
|
+
else:
|
|
101
|
+
return super().percent_point(y, V)
|
|
102
|
+
|
|
103
|
+
def partial_derivative(self, X):
|
|
104
|
+
r"""Compute partial derivative of cumulative distribution.
|
|
105
|
+
|
|
106
|
+
The partial derivative of the copula(CDF) is the conditional CDF.
|
|
107
|
+
|
|
108
|
+
.. math:: F(v|u) = \frac{\partial C(u,v)}{\partial u} =
|
|
109
|
+
C(u,v)\frac{((-\ln u)^{\theta} + (-\ln v)^{\theta})^{\frac{1}{\theta} - 1}}
|
|
110
|
+
{\theta(- \ln u)^{1 -\theta}}
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
X (np.ndarray)
|
|
114
|
+
y (float)
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
numpy.ndarray
|
|
118
|
+
|
|
119
|
+
"""
|
|
120
|
+
self.check_fit()
|
|
121
|
+
|
|
122
|
+
U, V = split_matrix(X)
|
|
123
|
+
|
|
124
|
+
if self.theta == 1:
|
|
125
|
+
return V
|
|
126
|
+
|
|
127
|
+
else:
|
|
128
|
+
t1 = np.power(-np.log(U), self.theta)
|
|
129
|
+
t2 = np.power(-np.log(V), self.theta)
|
|
130
|
+
p1 = self.cumulative_distribution(X)
|
|
131
|
+
p2 = np.power(t1 + t2, -1 + 1.0 / self.theta)
|
|
132
|
+
p3 = np.power(-np.log(V), self.theta - 1)
|
|
133
|
+
return p1 * p2 * p3 / V
|
|
134
|
+
|
|
135
|
+
def compute_theta(self):
|
|
136
|
+
r"""Compute theta parameter using Kendall's tau.
|
|
137
|
+
|
|
138
|
+
On Gumbel copula :math:`\tau` is defined as :math:`τ = \frac{θ−1}{θ}`
|
|
139
|
+
that we solve as :math:`θ = \frac{1}{1-τ}`
|
|
140
|
+
"""
|
|
141
|
+
if self.tau == 1:
|
|
142
|
+
raise ValueError("Tau value can't be 1")
|
|
143
|
+
|
|
144
|
+
return 1 / (1 - self.tau)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Independence module."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from copulas.bivariate.base import Bivariate, CopulaTypes
|
|
6
|
+
from copulas.bivariate.utils import split_matrix
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Independence(Bivariate):
|
|
10
|
+
"""This class represent the copula for two independent variables."""
|
|
11
|
+
|
|
12
|
+
copula_type = CopulaTypes.INDEPENDENCE
|
|
13
|
+
|
|
14
|
+
def fit(self, X):
|
|
15
|
+
"""Fit the copula to the given data.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
X (numpy.array): Probabilites in a matrix shaped (n, 2)
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
None
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def generator(self, t):
|
|
26
|
+
"""Compute the generator function for the Copula.
|
|
27
|
+
|
|
28
|
+
The generator function is a function f(t), such that an archimedian copula can be
|
|
29
|
+
defined as
|
|
30
|
+
|
|
31
|
+
C(u1, ..., uN) = f(f^-1(u1), ..., f^-1(uN)).
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
t(numpy.array)
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
np.array
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
return np.log(t)
|
|
41
|
+
|
|
42
|
+
def probability_density(self, X):
|
|
43
|
+
"""Compute the probability density for the independence copula."""
|
|
44
|
+
return np.all((0.0 <= X) & (X <= 1.0), axis=1).astype(float)
|
|
45
|
+
|
|
46
|
+
def cumulative_distribution(self, X):
|
|
47
|
+
"""Compute the cumulative distribution of the independence bivariate copula is the product.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
X(numpy.array): Matrix of shape (n,2), whose values are in [0, 1]
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
numpy.array: Cumulative distribution values of given input.
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
U, V = split_matrix(X)
|
|
57
|
+
return U * V
|
|
58
|
+
|
|
59
|
+
def partial_derivative(self, X):
|
|
60
|
+
"""Compute the conditional probability of one event conditiones to the other.
|
|
61
|
+
|
|
62
|
+
In the case of the independence copula, due to C(u,v) = u*v, we have that
|
|
63
|
+
F(u|v) = dC/du = v.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
X()
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
_, V = split_matrix(X)
|
|
70
|
+
return V
|
|
71
|
+
|
|
72
|
+
def percent_point(self, y, V):
|
|
73
|
+
"""Compute the inverse of conditional cumulative distribution :math:`F(u|v)^-1`.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
y: `np.ndarray` value of :math:`F(u|v)`.
|
|
77
|
+
v: `np.ndarray` given value of v.
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
self.check_fit()
|
|
81
|
+
return y
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Utilities for bivariate copulas."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def split_matrix(X):
|
|
7
|
+
"""Split an (n,2) numpy.array into two vectors.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
X(numpy.array): Matrix of shape (n,2)
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
tuple[numpy.array]: Both of shape (n,)
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
if len(X):
|
|
17
|
+
return X[:, 0], X[:, 1]
|
|
18
|
+
|
|
19
|
+
return np.array([]), np.array([])
|