Skip to content
Merged
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: 2 additions & 1 deletion chainladder/adjustments/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ def _get_hetero_adjustment(self):
pass

def transform(self, X):
"""If X and self are of different shapes, align self to X, else
"""
If X and self are of different shapes, align self to X, else
return self.

Parameters
Expand Down
6 changes: 4 additions & 2 deletions chainladder/adjustments/disposal.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ def fit(self, X: Triangle, y: None = None, sample_weight: Triangle | None = None
return self

def transform(self, X: Triangle, sample_weight: Triangle | None = None) -> Triangle:
"""If X and self are of different shapes, align self to X, else
"""
If X and self are of different shapes, align self to X, else
return self.

Parameters
Expand Down Expand Up @@ -318,7 +319,8 @@ def transform(self, X: Triangle, sample_weight: Triangle | None = None) -> Trian
return X_new

def fit_transform(self, X, y=None, sample_weight=None):
"""Fit and return transformed full_triangle_ based on the Disposal Rate
"""
Fit and return transformed full_triangle_ based on the Disposal Rate

Parameters
----------
Expand Down
6 changes: 4 additions & 2 deletions chainladder/adjustments/parallelogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ def __init__(
self.cumulative = cumulative

def fit(self, X, y=None, sample_weight=None):
"""Fit the model with X.
"""
Fit the model with X.

Parameters
----------
Expand Down Expand Up @@ -332,7 +333,8 @@ def _combine_duplicate_dates(self, r):
return (r.groupby(self.date_col)[self.change_col].prod() - 1).reset_index()

def transform(self, X, y=None, sample_weight=None):
"""If X and self are of different shapes, align self to X, else
"""
If X and self are of different shapes, align self to X, else
return self.

Parameters
Expand Down
3 changes: 2 additions & 1 deletion chainladder/adjustments/tests/test_parallelogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,8 @@ def test_cumulative_rejects_non_positive():


def test_cumulative_factor_predates_window():
"""A factor in force before the triangle window is honored, not dropped.
"""
A factor in force before the triangle window is honored, not dropped.

The earliest factor's effective date (2000) predates the triangle's
lookback window (origins start 2003), so it must still apply to the first
Expand Down
6 changes: 4 additions & 2 deletions chainladder/adjustments/trend.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ def __init__(self, trends=0.0, dates=None, axis="origin"):
self.axis = axis

def fit(self, X, y=None, sample_weight=None):
"""Fit the model with X.
"""
Fit the model with X.

Parameters
----------
Expand Down Expand Up @@ -193,7 +194,8 @@ def fit(self, X, y=None, sample_weight=None):
return self

def transform(self, X, y=None, sample_weight=None):
"""If X and self are of different shapes, align self to X, else
"""
If X and self are of different shapes, align self to X, else
return self.

Parameters
Expand Down
18 changes: 12 additions & 6 deletions chainladder/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class TriangleBase(

@property
def shape(self):
"""The 4-D shape of the Triangle: ``(index, columns, origin, development)``.
"""
The 4-D shape of the Triangle: ``(index, columns, origin, development)``.

Examples
--------
Expand All @@ -79,7 +80,8 @@ def shape(self):

@property
def dimensionality(self):
"""The dimensionality of the Triangle.
"""
The dimensionality of the Triangle.

Returns ``'empty'`` for a Triangle instantiated without data
(e.g. ``cl.Triangle()``), ``'single'`` for a Triangle holding a
Expand Down Expand Up @@ -107,7 +109,8 @@ def dimensionality(self):

@property
def empty(self):
"""Whether the Triangle contains any data.
"""
Whether the Triangle contains any data.

Mirrors ``pandas.DataFrame.empty``. Returns ``True`` for a Triangle
instantiated without data (e.g. ``cl.Triangle()``), whose ``values``
Expand Down Expand Up @@ -425,7 +428,8 @@ def is_ultimate(self) -> bool:

@property
def nan_triangle(self):
"""Given the current triangle shape and valuation, it determines the
"""
Given the current triangle shape and valuation, it determines the
appropriate placement of NANs in the triangle for future valuations.
This becomes useful when managing array arithmetic.

Expand Down Expand Up @@ -775,7 +779,8 @@ def __array_function__(self, func, types, args, kwargs):
return HANDLED_FUNCTIONS[func](*args, **kwargs)

def compute(self, *args, **kwargs):
"""Materialize a lazy dask-backed Triangle.
"""
Materialize a lazy dask-backed Triangle.

When ``values`` is a dask array, compute it and update
``array_backend`` to match the resulting array type. Returns ``self``
Expand Down Expand Up @@ -819,7 +824,8 @@ def _get_axis_value(self, axis):


def is_chainladder(estimator):
"""Return True if the given estimator is a chainladder based method.
"""
Return True if the given estimator is a chainladder based method.
Parameters
----------
estimator : object
Expand Down
18 changes: 12 additions & 6 deletions chainladder/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def has_zeta(self):

@property
def cdf_(self):
"""Cumulative development factors, ``ldf_`` converted with ``incr_to_cum``.
"""
Cumulative development factors, ``ldf_`` converted with ``incr_to_cum``.

Examples
--------
Expand Down Expand Up @@ -117,7 +118,8 @@ def cdf_(self):

@property
def pct_reported_(self):
"""Percentage of ultimate reported (or paid) at each development age,
"""
Percentage of ultimate reported (or paid) at each development age,
equal to the inverse of the cumulative development factor.

Examples
Expand Down Expand Up @@ -146,8 +148,10 @@ def pct_reported_(self):

@property
def pct_unreported_(self):
"""Percentage of ultimate still unreported (or unpaid) at each
development age, equal to ``1 - 1 / cdf_``."""
"""
Percentage of ultimate still unreported (or unpaid) at each
development age, equal to ``1 - 1 / cdf_``.
"""
if not self.has_ldf:
x = self.__class__.__name__
raise AttributeError(
Expand All @@ -164,7 +168,8 @@ def cum_zeta_(self):

@property
def ibnr_(self):
"""Outstanding development to ultimate: ``ultimate_`` minus the latest
"""
Outstanding development to ultimate: ``ultimate_`` minus the latest
diagonal (or the origin total, for incremental triangles).

Examples
Expand Down Expand Up @@ -227,7 +232,8 @@ def full_triangle_(self):
return _get_full_triangle(X, self.ultimate_, X.is_cumulative)

def pipe(self, func, *args, **kwargs):
"""Apply ``func(self, *args, **kwargs)``.
"""
Apply ``func(self, *args, **kwargs)``.

Parameters
----------
Expand Down
55 changes: 34 additions & 21 deletions chainladder/core/dunders.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@


class TriangleDunders:
"""Class that implements the dunder (double underscore) methods for the
Triangle class
"""
Class that implements the dunder (double underscore) methods for the Triangle class
"""

def _validate_arithmetic(self, other: Any) -> tuple:
Expand Down Expand Up @@ -263,7 +263,12 @@ def _slice_or_nan(obj, other, k):

@staticmethod
def _get_key_union(obj, other):
return set(list(obj.groups.indices.keys()) + list(other.groups.indices.keys()))
# fmt: off
return set(
list(obj.groups.indices.keys())
+ list(other.groups.indices.keys())
)
# fmt: on

def _arithmetic_mapper(self, obj, other, f):
"""Use Dask if available, otherwise basic list comprehension"""
Expand All @@ -277,7 +282,8 @@ def _arithmetic_mapper(self, obj, other, f):
return concat(c, 0).sort_index()

def __add__(self, other):
"""Element-wise addition.
"""
Element-wise addition.

Examples
--------
Expand Down Expand Up @@ -313,9 +319,10 @@ def __add__(self, other):
if isinstance(obj, TriangleGroupBy):

def f(k, self, obj, other):
return self._slice_or_nan(obj, other, k) + self._slice_or_nan(
other, obj, k
)
# fmt: off
return (self._slice_or_nan(obj, other, k) +
self._slice_or_nan(other, obj, k))
# fmt: on

obj = self._arithmetic_mapper(obj, other, f)
else:
Expand All @@ -327,7 +334,8 @@ def __radd__(self, other):
return self if other == 0 else self.__add__(other)

def __sub__(self, other):
"""Element-wise subtraction.
"""
Element-wise subtraction.

Examples
--------
Expand Down Expand Up @@ -361,9 +369,10 @@ def __sub__(self, other):
if isinstance(obj, TriangleGroupBy):

def f(k, self, obj, other):
return self._slice_or_nan(obj, other, k) - self._slice_or_nan(
other, obj, k
)
# fmt: off
return (self._slice_or_nan(obj, other, k) -
self._slice_or_nan(other, obj, k))
# fmt: on

obj = self._arithmetic_mapper(obj, other, f)
else:
Expand Down Expand Up @@ -404,7 +413,8 @@ def __abs__(self):
return obj

def __mul__(self, other):
"""Element-wise multiplication.
"""
Element-wise multiplication.

Examples
--------
Expand Down Expand Up @@ -438,9 +448,10 @@ def __mul__(self, other):
if isinstance(obj, TriangleGroupBy):

def f(k, self, obj, other):
return self._slice_or_nan(obj, other, k) * self._slice_or_nan(
other, obj, k
)
# fmt: off
return (self._slice_or_nan(obj, other, k) *
self._slice_or_nan(other, obj, k))
# fmt: on

obj = self._arithmetic_mapper(obj, other, f)
else:
Expand All @@ -455,9 +466,10 @@ def __pow__(self, other):
if isinstance(obj, TriangleGroupBy):

def f(k, self, obj, other):
return self._slice_or_nan(obj, other, k) ** self._slice_or_nan(
other, obj, k
)
# fmt: off
return (self._slice_or_nan(obj, other, k) **
self._slice_or_nan(other, obj, k))
# fmt: on

obj = self._arithmetic_mapper(obj, other, f)
else:
Expand Down Expand Up @@ -528,9 +540,10 @@ def __truediv__(self, other: Any):
if isinstance(obj, TriangleGroupBy):

def f(k, self, obj, other):
return self._slice_or_nan(obj, other, k) / self._slice_or_nan(
other, obj, k
)
# fmt: off
return (self._slice_or_nan(obj, other, k) /
self._slice_or_nan(other, obj, k))
# fmt: on

obj = self._arithmetic_mapper(obj, other, f)
else:
Expand Down
30 changes: 20 additions & 10 deletions chainladder/core/io.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Support Triangle I/O capabilities.
"""

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
Expand All @@ -13,7 +14,8 @@

class TriangleIO:
def to_pickle(self, path, protocol=None):
""" Serializes triangle object to pickle.
"""
Serializes triangle object to pickle.

Parameters
----------
Expand Down Expand Up @@ -53,7 +55,8 @@ def to_pickle(self, path, protocol=None):
dill.dump(self, pkl)

def to_json(self):
""" Serializes triangle object to json format
"""
Serializes triangle object to json format

Returns
-------
Expand Down Expand Up @@ -88,8 +91,13 @@ def to_json(self):
"is_pattern": self.is_pattern,
"columns": list(self.columns),
}
out = self.cum_to_incr().dev_to_val().to_frame(
keepdims=True, origin_as_datetime=True).fillna(0)
out = (
self
.cum_to_incr()
.dev_to_val()
.to_frame(keepdims=True, origin_as_datetime=True)
.fillna(0)
)
x = out.reset_index().to_json(orient="split", date_unit="ns")
json_dict = {"metadata": json.dumps(metadata), "data": x}
sub_tris = [k for k, v in vars(self).items() if isinstance(v, TriangleIO)]
Expand All @@ -99,17 +107,18 @@ def to_json(self):
dfs = [k for k, v in vars(self).items() if isinstance(v, pd.DataFrame)]
json_dict["dfs"] = {df: getattr(self, df).to_json() for df in dfs}
dfs = [k for k, v in vars(self).items() if isinstance(v, pd.Series)]
json_dict["dfs"].update(
{df: getattr(self, df).to_frame().to_json() for df in dfs}
)
json_dict["dfs"].update({
df: getattr(self, df).to_frame().to_json() for df in dfs
})
return json.dumps(json_dict)


class EstimatorIO:
""" Class intended to allow persistence of estimator objects """
"""Class intended to allow persistence of estimator objects"""

def to_pickle(self, path, protocol=None):
""" Serializes triangle object to pickle.
"""
Serializes triangle object to pickle.

Parameters
----------
Expand Down Expand Up @@ -149,7 +158,8 @@ def to_pickle(self, path, protocol=None):
dill.dump(self, pkl)

def to_json(self):
""" Serializes triangle object to json format
"""
Serializes triangle object to json format

Returns
-------
Expand Down
Loading
Loading