Skip to content
Snippets Groups Projects
Commit 575a5b6e authored by Peter Lünenschloß's avatar Peter Lünenschloß
Browse files

fix roll method

parent 8b8c9e40
No related branches found
No related tags found
1 merge request!843fix roll method
......@@ -323,13 +323,13 @@ function:
.. doctest:: exampleOD
>>> qc = qc.roll(field='incidents_residuals', target='incidents_scores', func=z_score, window='27D')
>>> qc = qc.roll(field='incidents_residuals', target='incidents_scores', func=z_score, window='27D', min_periods=27)
.. plot::
:context: close-figs
:include-source: False
qc = qc.roll(field='incidents_residuals', target='incidents_scores', func=z_score, window='27D')
qc = qc.roll(field='incidents_residuals', target='incidents_scores', func=z_score, window='27D', min_periods=27)
Optimization by Decomposition
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......
......@@ -117,6 +117,10 @@ class RollingMixin:
DeprecationWarning,
)
validateFuncSelection(func, allow_operator_str=True)
validateWindow(window)
validateMinPeriods(min_periods)
# HINT: checking in _roll
self._data, self._flags = _roll(
data=self._data,
......@@ -146,70 +150,17 @@ def _roll(
validateMinPeriods(min_periods)
to_fit = data[field].copy()
flags_col = flags[field].copy()
if to_fit.empty:
return data, flags
regular = getFreqDelta(to_fit.index)
# starting with the annoying case: finding the rolling interval
# centers of not-harmonized input time series:
if center and not regular:
if isinstance(window, int):
raise NotImplementedError(
"Integer based window size is not supported for not-harmonized"
'sample series when rolling with "center=True".'
)
# get interval centers
centers = np.floor(
(
to_fit.rolling(
pd.Timedelta(window) / 2, closed="both", min_periods=min_periods
).count()
)
)
centers = centers.drop(centers[centers.isna()].index)
centers = centers.astype(int)
roller = to_fit.rolling(
pd.Timedelta(window), closed="both", min_periods=min_periods
)
try:
means = getattr(roller, func.__name__)()
except AttributeError:
means = to_fit.rolling(
pd.Timedelta(window), closed="both", min_periods=min_periods
).apply(func)
def center_func(x, y=centers):
pos = x.index[int(len(x) - y[x.index[-1]])]
return y.index.get_loc(pos)
centers_iloc = (
centers.rolling(window, closed="both")
.apply(center_func, raw=False)
.astype(int)
)
temp = means.copy()
for k in centers_iloc.iteritems():
means.iloc[k[1]] = temp[k[0]]
# last values are false, due to structural reasons:
means[means.index[centers_iloc[-1]] : means.index[-1]] = np.nan
# everything is more easy if data[field] is harmonized:
d_roller = to_fit.rolling(window, min_periods=min_periods, center=center)
if isinstance(func, str):
to_fit = getattr(d_roller, func)()
else:
if isinstance(window, str):
window = pd.Timedelta(window) // regular
if (window % 2 == 0) & center:
window = int(window - 1)
roller = to_fit.rolling(window=window, center=center, closed="both")
try:
means = getattr(roller, func.__name__)()
except AttributeError:
means = to_fit.rolling(window=window, center=center, closed="both").apply(
func
)
data[field] = means
worst = flags[field].rolling(window, center=True, min_periods=min_periods).max()
flags[field] = worst
to_fit = d_roller.apply(func)
flags_col = flags_col.rolling(window, min_periods=min_periods, center=center).max()
data[field] = to_fit
flags[field] = flags_col
return data, flags
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment