diff --git a/saqc/funcs/interpolation.py b/saqc/funcs/interpolation.py index 60bdbf29d0ea5dde009fb5e49e041bf220e62b60..3c2a422eb202d085bbaf9ca2988fac17f3246e91 100644 --- a/saqc/funcs/interpolation.py +++ b/saqc/funcs/interpolation.py @@ -144,7 +144,7 @@ class InterpolationMixin: method: _SUPPORTED_METHODS, order: int = 2, limit: int | None = None, - extrapolate: Literal['forward', 'backward', 'both'] = None, + extrapolate: Literal["forward", "backward", "both"] = None, flag: float = UNFLAGGED, **kwargs, ) -> "SaQC": @@ -187,7 +187,7 @@ class InterpolationMixin: method, order=order, gap_limit=limit, - extrapolate=extrapolate + extrapolate=extrapolate, ) interpolated = self._data[field].isna() & inter_data.notna() diff --git a/saqc/lib/ts_operators.py b/saqc/lib/ts_operators.py index 0347c757dffd61f4211b1f0f8d9af706270c3870..6573fd883ef260f1a4773e0482591ced93d426cf 100644 --- a/saqc/lib/ts_operators.py +++ b/saqc/lib/ts_operators.py @@ -275,25 +275,40 @@ def meanQC(data, max_nan_total=np.inf, max_nan_consec=np.inf): ) -def _interpolWrapper(x, order=1, method="time", limit_area='inside', limit_direction=None): +def _interpolWrapper( + x, order=1, method="time", limit_area="inside", limit_direction=None +): """ Function that automatically modifies the interpolation level or returns uninterpolated input data if the data configuration breaks the interpolation method at the selected degree. """ - min_vals_dict = {'nearest': 2, 'slinear': 2, 'quadratic': 3, 'cubic':4, 'spline':order+1, 'polynomial':order+1, - 'piecewise_polynomial': 2, 'pchip': 2, 'akima': 2, 'cubicspline': 2} + min_vals_dict = { + "nearest": 2, + "slinear": 2, + "quadratic": 3, + "cubic": 4, + "spline": order + 1, + "polynomial": order + 1, + "piecewise_polynomial": 2, + "pchip": 2, + "akima": 2, + "cubicspline": 2, + } min_vals = min_vals_dict.get(method, 0) if (x.size < 3) | (x.count() < min_vals): return x else: - return x.interpolate(method=method, order=order, limit_area=limit_area, limit_direction=limit_direction) + return x.interpolate( + method=method, + order=order, + limit_area=limit_area, + limit_direction=limit_direction, + ) -def interpolateNANs( - data, method, order=2, gap_limit=2, extrapolate=None -): +def interpolateNANs(data, method, order=2, gap_limit=2, extrapolate=None): """ The function interpolates nan-values (and nan-grids) in timeseries data. It can be passed all the method keywords from the pd.Series.interpolate method and will @@ -338,7 +353,9 @@ def interpolateNANs( gap_mask = gap_mask & gap_mask.shift(-1, fill_value=True) else: # If the gap_size is bigger we make an flip-rolling combo to backpropagate the False values - gap_mask = ~((~gap_mask[::-1]).rolling(gap_limit, min_periods=0).sum() > 0)[::-1] + gap_mask = ~( + (~gap_mask[::-1]).rolling(gap_limit, min_periods=0).sum() > 0 + )[::-1] # memorizing the index for later reindexing pre_index = data.index @@ -350,7 +367,12 @@ def interpolateNANs( if method in ["linear", "time"]: # in the case of linear interpolation, not much can go wrong/break so this conditional branch has efficient # finish by just calling pandas interpolation routine to fill the gaps remaining in the data: - data.interpolate(method=method, inplace=True, limit_area=limit_area, limit_direction=extrapolate) + data.interpolate( + method=method, + inplace=True, + limit_area=limit_area, + limit_direction=extrapolate, + ) else: # if the method that is interpolated with, depends on not only the left and right border points of any gap, @@ -365,7 +387,7 @@ def interpolateNANs( "order": order, "method": method, "limit_area": limit_area, - "limit_direction": extrapolate + "limit_direction": extrapolate, }, ) # finally reinsert the dropped data gaps @@ -612,6 +634,4 @@ def linearInterpolation(data, inter_limit=2): def polynomialInterpolation(data, inter_limit=2, inter_order=2): - return interpolateNANs( - data, "polynomial", gap_limit=inter_limit, order=inter_order - ) + return interpolateNANs(data, "polynomial", gap_limit=inter_limit, order=inter_order)