From d998ab0191c4c86ae8c4fe9b809955a999b33f50 Mon Sep 17 00:00:00 2001 From: John Bogaardt Date: Sat, 17 Jun 2023 12:19:27 -0600 Subject: [PATCH] prep for 0.8.16 --- chainladder/core/base.py | 2 +- chainladder/core/pandas.py | 1 - chainladder/core/slice.py | 30 +++++++------------------- chainladder/development/development.py | 11 +++++++++- docs/library/releases.md | 16 ++++++++++++++ 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/chainladder/core/base.py b/chainladder/core/base.py index 089cb350..4362069e 100644 --- a/chainladder/core/base.py +++ b/chainladder/core/base.py @@ -256,7 +256,7 @@ def _to_datetime(data, fields, period_end=False, format=None): def _development_lag(origin, valuation): """For tabular format, this will convert the origin/valuation difference to a development lag""" - return ((valuation - origin) / (365/12)).round('1d').dt.days + return ((valuation - origin) / (365.25/12)).round('1d').dt.days @staticmethod diff --git a/chainladder/core/pandas.py b/chainladder/core/pandas.py index 8266b119..247a224d 100644 --- a/chainladder/core/pandas.py +++ b/chainladder/core/pandas.py @@ -389,7 +389,6 @@ def add_groupby_agg_func(cls, k, v): def agg_func(self, *args, **kwargs): from chainladder.utils import concat - xp = self.obj.get_array_module() obj = self.obj.copy() auto_sparse = kwargs.pop("auto_sparse", True) diff --git a/chainladder/core/slice.py b/chainladder/core/slice.py index 8c2acf94..9eb22bdb 100644 --- a/chainladder/core/slice.py +++ b/chainladder/core/slice.py @@ -14,8 +14,7 @@ def __init__(self, obj): def get_idx(self, idx): """ Returns a slice of the original Triangle """ - from chainladder.core.triangle import Triangle - obj = Triangle() + obj = self.obj.copy() i_idx = _LocBase._contig_slice(idx[0]) c_idx = _LocBase._contig_slice(idx[1]) o_idx = _LocBase._contig_slice(idx[2]) @@ -23,27 +22,14 @@ def get_idx(self, idx): if type(o_idx) != slice or type(d_idx) != slice: raise ValueError("Fancy indexing on origin/development is not supported.") if type(i_idx) is slice or type(c_idx) is slice: - obj.values = self.obj.values[i_idx, c_idx, o_idx, d_idx] + obj.values = obj.values[i_idx, c_idx, o_idx, d_idx] else: - obj.values = self.obj.values[i_idx, :, o_idx, d_idx][:, c_idx, ...] - obj.kdims = self.obj.kdims[i_idx] - obj.vdims = self.obj.vdims[c_idx] - obj.odims = self.obj.odims[o_idx] - obj.ddims = self.obj.ddims[d_idx] - obj.iloc = Ilocation(obj) - obj.loc = Location(obj) - obj.origin_grain = self.obj.origin_grain - obj.development_grain = self.obj.development_grain - obj.key_labels = self.obj.key_labels - obj.origin_close = self.obj.origin_close - obj.is_pattern = self.obj.is_pattern - obj.is_cumulative = self.obj.is_cumulative - obj.virtual_columns = self.obj.virtual_columns - obj.array_backend = self.obj.array_backend - obj.valuation_date = self.obj.valuation_date - obj.valuation_date = np.minimum(obj.valuation.max(), self.obj.valuation_date) - for t in self.obj.subtriangles + ['w_'] if hasattr(self.obj, 'w_') else []: - setattr(obj, t, getattr(self.obj, t)) + obj.values = obj.values[i_idx, :, o_idx, d_idx][:, c_idx, ...] + obj.kdims = obj.kdims[i_idx] + obj.vdims = obj.vdims[c_idx] + obj.odims, obj.ddims = obj.odims[o_idx], obj.ddims[d_idx] + obj.iloc, obj.loc = Ilocation(obj), Location(obj) + obj.valuation_date = np.minimum(obj.valuation.max(), obj.valuation_date) return obj @staticmethod diff --git a/chainladder/development/development.py b/chainladder/development/development.py index 89184cfa..48f5c6a2 100644 --- a/chainladder/development/development.py +++ b/chainladder/development/development.py @@ -43,6 +43,12 @@ class Development(DevelopmentBase): The minimum number of link ratio(s) required for LDF calculation drop_valuation: str or list of str (default = None) Drops specific valuation periods. str must be date convertible. + fillna: float, (default = None) + Used to fill in zero or nan values of an triangle with some non-zero + amount. When an link-ratio has zero as its denominator, it is automatically + excluded from the ``ldf_`` calculation. For the specific case of 'volume' + averaging in a deterministic method, this may be reasonable. For all other + averages and stochastic methods, this assumption should be avoided. groupby: An option to group levels of the triangle index together for the purposes of estimating patterns. If omitted, each level of the triangle @@ -115,7 +121,10 @@ def fit(self, X, y=None, sample_weight=None): # Triangle must be cumulative and in "development" mode obj = self._set_fit_groups(X).incr_to_cum().val_to_dev().copy() xp = obj.get_array_module() - tri_array = num_to_nan(obj.values.copy()) + if self.fillna: + tri_array = num_to_nan((obj + self.fillna).values) + else: + tri_array = num_to_nan(obj.values.copy()) average_ = self._validate_assumption(X, self.average, axis=3)[... , :X.shape[3]-1] self.average_ = average_.flatten() n_periods_ = self._validate_assumption(X, self.n_periods, axis=3)[... , :X.shape[3]-1] diff --git a/docs/library/releases.md b/docs/library/releases.md index 62694a26..7bbd030d 100644 --- a/docs/library/releases.md +++ b/docs/library/releases.md @@ -1,6 +1,22 @@ # {octicon}`megaphone` Releases & Changelog ## Version 0.8 +### Version 0.8.16 + +Release Date: Jun 17, 2023 + +**What's Changed** +* fix for [\#409](https://github.com/casact/chainladder-python/issues/409) +* fix for [\#411](https://github.com/casact/chainladder-python/issues/411) +* fix for [\#438](https://github.com/casact/chainladder-python/issues/438) + +## New Contributors +* [@MatthewCaseres](https://github.com/MatthewCaseres) made their first contribution. +* [@andrejakobsen](https://github.com/andrejakobsen) made their first contribution. + + + + ### Version 0.8.15