Source code for climb.tool.impl.data_suite.third_party.copulas

# -*- coding: utf-8 -*-

"""Top-level package for Copulas."""

__author__ = "MIT Data To AI Lab"
__email__ = ("dailabmit@gmail.com",)
__version__ = "0.6.0"

import contextlib
import importlib
from copy import deepcopy

import numpy as np
import pandas as pd

EPSILON = np.finfo(np.float32).eps


[docs] class NotFittedError(Exception): pass
[docs] @contextlib.contextmanager def random_seed(seed): state = np.random.get_state() np.random.seed(seed) try: yield finally: np.random.set_state(state)
[docs] def random_state(function): def wrapper(self, *args, **kwargs): if self.random_seed is None: return function(self, *args, **kwargs) else: with random_seed(self.random_seed): return function(self, *args, **kwargs) return wrapper
[docs] def get_instance(obj, **kwargs): """Create new instance of the ``obj`` argument. Args: obj (str, type, instance): """ instance = None if isinstance(obj, str): package, name = obj.rsplit(".", 1) instance = getattr(importlib.import_module(package), name)(**kwargs) elif isinstance(obj, type): instance = obj(**kwargs) else: if kwargs: instance = obj.__class__(**kwargs) else: args = getattr(obj, "__args__", tuple()) kwargs = getattr(obj, "__kwargs__", {}) instance = obj.__class__(*args, **kwargs) return instance
[docs] def store_args(__init__): """Save ``*args`` and ``**kwargs`` used in the ``__init__`` of a copula. Args: __init__(callable): ``__init__`` function to store their arguments. Returns: callable: Decorated ``__init__`` function. """ def new__init__(self, *args, **kwargs): args_copy = deepcopy(args) kwargs_copy = deepcopy(kwargs) __init__(self, *args, **kwargs) self.__args__ = args_copy self.__kwargs__ = kwargs_copy return new__init__
[docs] def get_qualified_name(_object): """Return the Fully Qualified Name from an instance or class.""" module = _object.__module__ if hasattr(_object, "__name__"): _class = _object.__name__ else: _class = _object.__class__.__name__ return module + "." + _class
[docs] def vectorize(function): """Allow a method that only accepts scalars to accept vectors too. This decorator has two different behaviors depending on the dimensionality of the array passed as an argument: **1-d array** It will work under the assumption that the `function` argument is a callable with signature:: function(self, X, *args, **kwargs) where X is an scalar magnitude. In this case the arguments of the input array will be given one at a time, and both the input and output of the decorated function will have shape (n,). **2-d array** It will work under the assumption that the `function` argument is a callable with signature:: function(self, X0, ..., Xj, *args, **kwargs) where `Xi` are scalar magnitudes. It will pass the contents of each row unpacked on each call. The input is espected to have shape (n, j), the output a shape of (n,) It will return a function that is guaranteed to return a `numpy.array`. Args: function(callable): Function that only accept and return scalars. Returns: callable: Decorated function that can accept and return :attr:`numpy.array`. """ def decorated(self, X, *args, **kwargs): if not isinstance(X, np.ndarray): return function(self, X, *args, **kwargs) if len(X.shape) == 1: X = X.reshape([-1, 1]) if len(X.shape) == 2: return np.fromiter((function(self, *x, *args, **kwargs) for x in X), np.dtype("float64")) else: raise ValueError("Arrays of dimensionality higher than 2 are not supported.") decorated.__doc__ = function.__doc__ return decorated
[docs] def scalarize(function): """Allow methods that only accepts 1-d vectors to work with scalars. Args: function(callable): Function that accepts and returns vectors. Returns: callable: Decorated function that accepts and returns scalars. """ def decorated(self, X, *args, **kwargs): scalar = not isinstance(X, np.ndarray) if scalar: X = np.array([X]) result = function(self, X, *args, **kwargs) if scalar: result = result[0] return result decorated.__doc__ = function.__doc__ return decorated
[docs] def check_valid_values(function): """Raises an exception if the given values are not supported. Args: function(callable): Method whose unique argument is a numpy.array-like object. Returns: callable: Decorated function Raises: ValueError: If there are missing or invalid values or if the dataset is empty. """ def decorated(self, X, *args, **kwargs): if isinstance(X, pd.DataFrame): W = X.values else: W = X if not len(W): raise ValueError("Your dataset is empty.") if not (np.issubdtype(W.dtype, np.floating) or np.issubdtype(W.dtype, np.integer)): raise ValueError("There are non-numerical values in your data.") if np.isnan(W).any().any(): raise ValueError("There are nan values in your data.") return function(self, X, *args, **kwargs) return decorated