Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added Copula Bivariate Joe Functionality #385

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/Copulas.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions copulas/bivariate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from copulas.bivariate.clayton import Clayton
from copulas.bivariate.frank import Frank
from copulas.bivariate.gumbel import Gumbel
from copulas.bivariate.joe import Joe
from copulas.bivariate.utils import split_matrix

__all__ = (
Expand All @@ -16,6 +17,7 @@
'CopulaTypes',
'Frank',
'Gumbel',
'Joe'
)


Expand Down Expand Up @@ -96,8 +98,13 @@ def _compute_candidates(copulas, left_tail, right_tail):
X_right = np.column_stack((right_tail, right_tail))

for copula in copulas:
left.append(copula.cumulative_distribution(X_left) / np.power(left_tail, 2))
right.append(_compute_tail(copula.cumulative_distribution(X_right), right_tail))
if isinstance(copula, Joe):
# Compute dependencies for Joe copula
left.append(...)
right.append(...)
else:
left.append(copula.cumulative_distribution(X_left) / np.power(left_tail, 2))
right.append(_compute_tail(copula.cumulative_distribution(X_right), right_tail))

return left, right

Expand Down Expand Up @@ -140,7 +147,7 @@ def select_copula(X):
copula_candidates = [frank]

# append copulas into the candidate list
for copula_class in [Clayton, Gumbel]:
for copula_class in [Clayton, Gumbel, Joe]:
try:
copula = copula_class()
copula.tau = frank.tau
Expand Down
87 changes: 87 additions & 0 deletions copulas/bivariate/joe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import numpy as np
from copulas.bivariate.base import Bivariate, CopulaTypes
from copulas.bivariate.utils import split_matrix

class Joe(Bivariate):
"""Class for Joe copula model."""

copula_type = CopulaTypes.JOE
theta_interval = [0, float('inf')]
invalid_thetas = [0]

def __init__(self, theta=1):
"""
Initialize a Joe copula.

Parameters:
- theta (float): The theta parameter of the Joe copula. Default is 1.
"""
self.theta = theta

def generator(self, t):
"""
Compute the generator function of the Joe copula.

The generator function of the Joe copula is defined as:

.. math:: G(t) = -((1 - t^(-theta))^(-1/theta))

Parameters:
- t (float or np.array): The value(s) at which to evaluate the generator.

Returns:
- float or np.array: The value(s) of the generator function at t.
"""
return -((1 - t ** (-self.theta)) ** (1 / self.theta))

def pdf(self, X):
"""
Compute the probability density function for the Joe copula.

The probability density function (PDF) for the Joe copula is given by:

.. math:: c(u, v) = (theta - 1) * (u^(-theta) + v^(-theta) - 1)^(theta - 2) * u^(-theta - 1) * v^(-theta - 1)

Parameters:
- X (np.array): The input array of shape (n, 2) containing pairs of values (u, v).

Returns:
- np.array: The probability density values for each pair in X.
"""
U, V = split_matrix(X)
return (self.theta - 1) * (U ** (-self.theta) + V ** (-self.theta) - 1) ** (self.theta - 2) * U ** (-self.theta - 1) * V ** (-self.theta - 1)

def cdf(self, X):
"""
Compute the cumulative distribution function for the Joe copula.

The cumulative distribution function (CDF) for the Joe copula is given by:

.. math:: C(u, v) = (u^(-theta) + v^(-theta) - 1)^theta

Parameters:
- X (np.array): The input array of shape (n, 2) containing pairs of values (u, v).

Returns:
- np.array: The cumulative distribution values for each pair in X.
"""
U, V = split_matrix(X)
return (U ** (-self.theta) + V ** (-self.theta) - 1) ** self.theta

def percent_point(self, y, V):
"""
Compute the inverse of conditional cumulative distribution :math:`C(u|v)^{-1}`.

The inverse of conditional cumulative distribution :math:`C(u|v)^{-1}` for the Joe copula
is given by:

.. math:: (y^(1/theta) + v^(-theta) - 1)^(-1/theta)

Parameters:
- y (float or np.array): The value(s) of :math:`C(u|v)`.
- V (float or np.array): The given value(s) of v.

Returns:
- float or np.array: The inverse of conditional cumulative distribution values.
"""
return (y ** (1 / self.theta) + V ** (-self.theta) - 1) ** (-1 / self.theta)