Skip to content
This repository was archived by the owner on Feb 2, 2024. It is now read-only.

Commit 9f63b4a

Browse files
Overload series.rolling.skew() (#444)
* Overload series.rolling.skew() * Remove excess code for series.rolling.skew() * Minor fix in test for series.rolling.skew() * Move method std back Co-authored-by: Alexander Kalistratov <alexander.kalistratov@intel.com>
1 parent 50178e8 commit 9f63b4a

File tree

3 files changed

+106
-5
lines changed

3 files changed

+106
-5
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# *****************************************************************************
2+
# Copyright (c) 2019, Intel Corporation All rights reserved.
3+
#
4+
# Redistribution and use in source and binary forms, with or without
5+
# modification, are permitted provided that the following conditions are met:
6+
#
7+
# Redistributions of source code must retain the above copyright notice,
8+
# this list of conditions and the following disclaimer.
9+
#
10+
# Redistributions in binary form must reproduce the above copyright notice,
11+
# this list of conditions and the following disclaimer in the documentation
12+
# and/or other materials provided with the distribution.
13+
#
14+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17+
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
18+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21+
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23+
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24+
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
# *****************************************************************************
26+
27+
import pandas as pd
28+
from numba import njit
29+
30+
31+
@njit
32+
def series_rolling_skew():
33+
series = pd.Series([4, 3, 5, 2, 6]) # Series of 4, 3, 5, 2, 6
34+
out_series = series.rolling(3).skew()
35+
36+
return out_series # Expect series of NaN, NaN, 0.000000, 0.935220, -1.293343
37+
38+
39+
print(series_rolling_skew())

sdc/datatypes/hpat_pandas_series_rolling_functions.py

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,31 @@ def arr_quantile(arr, q):
153153
return numpy.quantile(arr, q)
154154

155155

156+
@register_jitable
157+
def _moment(arr, moment):
158+
mn = numpy.mean(arr)
159+
s = numpy.power((arr - mn), moment)
160+
161+
return numpy.mean(s)
162+
163+
164+
@register_jitable
165+
def arr_skew(arr):
166+
"""Calculate unbiased skewness of values"""
167+
n = len(arr)
168+
if n < 3:
169+
return numpy.nan
170+
171+
m2 = _moment(arr, 2)
172+
m3 = _moment(arr, 3)
173+
val = 0 if m2 == 0 else m3 / m2 ** 1.5
174+
175+
if (n > 2) & (m2 > 0):
176+
val = numpy.sqrt((n - 1.0) * n) / (n - 2.0) * m3 / m2 ** 1.5
177+
178+
return val
179+
180+
156181
@register_jitable
157182
def arr_std(arr, ddof):
158183
"""Calculate standard deviation of values"""
@@ -247,6 +272,8 @@ def impl(self):
247272
gen_hpat_pandas_series_rolling_impl(arr_median, float64))
248273
hpat_pandas_rolling_series_min_impl = register_jitable(
249274
gen_hpat_pandas_series_rolling_impl(arr_min, float64))
275+
hpat_pandas_rolling_series_skew_impl = register_jitable(
276+
gen_hpat_pandas_series_rolling_impl(arr_skew, float64))
250277
hpat_pandas_rolling_series_sum_impl = register_jitable(
251278
gen_hpat_pandas_series_rolling_impl(arr_sum, float64))
252279

@@ -268,7 +295,7 @@ def hpat_pandas_series_rolling_corr(self, other=None, pairwise=None):
268295

269296
nan_other = isinstance(other, (Omitted, NoneType)) or other is None
270297

271-
def hpat_pandas_rolling_series_std_impl(self, other=None, pairwise=None):
298+
def hpat_pandas_rolling_series_corr_impl(self, other=None, pairwise=None):
272299
win = self._window
273300
minp = self._min_periods
274301

@@ -309,7 +336,7 @@ def calc_corr(main, other, minp):
309336

310337
return pandas.Series(output_arr)
311338

312-
return hpat_pandas_rolling_series_std_impl
339+
return hpat_pandas_rolling_series_corr_impl
313340

314341

315342
@sdc_overload_method(SeriesRollingType, 'count')
@@ -386,7 +413,7 @@ def hpat_pandas_series_rolling_cov(self, other=None, pairwise=None, ddof=1):
386413

387414
nan_other = isinstance(other, (Omitted, NoneType)) or other is None
388415

389-
def hpat_pandas_rolling_series_std_impl(self, other=None, pairwise=None, ddof=1):
416+
def hpat_pandas_rolling_series_cov_impl(self, other=None, pairwise=None, ddof=1):
390417
win = self._window
391418
minp = self._min_periods
392419

@@ -427,7 +454,7 @@ def calc_cov(main, other, ddof, minp):
427454

428455
return pandas.Series(output_arr)
429456

430-
return hpat_pandas_rolling_series_std_impl
457+
return hpat_pandas_rolling_series_cov_impl
431458

432459

433460
@sdc_overload_method(SeriesRollingType, 'max')
@@ -604,6 +631,15 @@ def calc_quantile(arr, quantile, minp):
604631
return hpat_pandas_rolling_series_quantile_impl
605632

606633

634+
@sdc_overload_method(SeriesRollingType, 'skew')
635+
def hpat_pandas_series_rolling_skew(self):
636+
637+
ty_checker = TypeChecker('Method rolling.skew().')
638+
ty_checker.check(self, SeriesRollingType)
639+
640+
return hpat_pandas_rolling_series_skew_impl
641+
642+
607643
@sdc_overload_method(SeriesRollingType, 'sum')
608644
def hpat_pandas_series_rolling_sum(self):
609645
"""
@@ -692,7 +728,7 @@ def culc_std(arr, ddof, minp):
692728
arr_range = input_arr[:i + 1]
693729
output_arr[i] = culc_std(arr_range, ddof, minp)
694730

695-
for i in prange(min(win, length), length):
731+
for i in prange(boundary, length):
696732
arr_range = input_arr[i + 1 - win:i + 1]
697733
output_arr[i] = culc_std(arr_range, ddof, minp)
698734

@@ -818,6 +854,13 @@ def culc_var(arr, ddof, minp):
818854
"""
819855
})
820856

857+
hpat_pandas_series_rolling_skew.__doc__ = hpat_pandas_series_rolling_docstring_tmpl.format(**{
858+
'method_name': 'skew',
859+
'example_caption': 'Unbiased rolling skewness.',
860+
'limitations_block': '',
861+
'extra_params': ''
862+
})
863+
821864
hpat_pandas_series_rolling_std.__doc__ = hpat_pandas_series_rolling_docstring_tmpl.format(**{
822865
'method_name': 'std',
823866
'example_caption': 'Calculate rolling standard deviation.',

sdc/tests/test_rolling.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,25 @@ def test_impl(quantile, interpolation):
800800
hpat_func(0.5, 'lower')
801801
self.assertIn('interpolation value not "linear"', str(raises.exception))
802802

803+
@skip_sdc_jit('Series.rolling.skew() unsupported Series index')
804+
def test_series_rolling_skew(self):
805+
def test_impl(series, window, min_periods):
806+
return series.rolling(window, min_periods).skew()
807+
808+
hpat_func = self.jit(test_impl)
809+
810+
all_data = test_global_input_data_float64
811+
indices = [list(range(len(data)))[::-1] for data in all_data]
812+
for data, index in zip(all_data, indices):
813+
series = pd.Series(data, index, name='A')
814+
for window in range(3, len(series) + 1):
815+
for min_periods in range(window + 1):
816+
with self.subTest(series=series, window=window,
817+
min_periods=min_periods):
818+
ref_result = test_impl(series, window, min_periods)
819+
jit_result = hpat_func(series, window, min_periods)
820+
pd.testing.assert_series_equal(jit_result, ref_result)
821+
803822
@skip_sdc_jit('Series.rolling.std() unsupported Series index')
804823
def test_series_rolling_std(self):
805824
test_impl = series_rolling_std_usecase

0 commit comments

Comments
 (0)