Skip to content

Commit 23cdcf7

Browse files
Backport PR #38909: BUG: Fixed regression in rolling.skew and rolling.kurt modifying object (#38945)
1 parent e793c4b commit 23cdcf7

File tree

3 files changed

+22
-18
lines changed

3 files changed

+22
-18
lines changed

doc/source/whatsnew/v1.2.1.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Fixed regressions
3737
- Fixed regression in :meth:`.GroupBy.sem` where the presence of non-numeric columns would cause an error instead of being dropped (:issue:`38774`)
3838
- Fixed regression in :func:`read_excel` with non-rawbyte file handles (:issue:`38788`)
3939
- Bug in :meth:`read_csv` with ``float_precision="high"`` caused segfault or wrong parsing of long exponent strings. This resulted in a regression in some cases as the default for ``float_precision`` was changed in pandas 1.2.0 (:issue:`38753`)
40-
-
40+
- Fixed regression in :meth:`Rolling.skew` and :meth:`Rolling.kurt` modifying the object inplace (:issue:`38908`)
4141

4242
.. ---------------------------------------------------------------------------
4343

pandas/_libs/window/aggregations.pyx

+14-12
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ def roll_skew(ndarray[float64_t] values, ndarray[int64_t] start,
523523
float64_t x = 0, xx = 0, xxx = 0
524524
int64_t nobs = 0, i, j, N = len(values), nobs_mean = 0
525525
int64_t s, e
526-
ndarray[float64_t] output, mean_array
526+
ndarray[float64_t] output, mean_array, values_copy
527527
bint is_monotonic_increasing_bounds
528528

529529
minp = max(minp, 3)
@@ -532,10 +532,11 @@ def roll_skew(ndarray[float64_t] values, ndarray[int64_t] start,
532532
)
533533
output = np.empty(N, dtype=float)
534534
min_val = np.nanmin(values)
535+
values_copy = np.copy(values)
535536

536537
with nogil:
537538
for i in range(0, N):
538-
val = values[i]
539+
val = values_copy[i]
539540
if notnan(val):
540541
nobs_mean += 1
541542
sum_val += val
@@ -544,7 +545,7 @@ def roll_skew(ndarray[float64_t] values, ndarray[int64_t] start,
544545
if min_val - mean_val > -1e5:
545546
mean_val = round(mean_val)
546547
for i in range(0, N):
547-
values[i] = values[i] - mean_val
548+
values_copy[i] = values_copy[i] - mean_val
548549

549550
for i in range(0, N):
550551

@@ -556,7 +557,7 @@ def roll_skew(ndarray[float64_t] values, ndarray[int64_t] start,
556557
if i == 0 or not is_monotonic_increasing_bounds:
557558

558559
for j in range(s, e):
559-
val = values[j]
560+
val = values_copy[j]
560561
add_skew(val, &nobs, &x, &xx, &xxx, &compensation_x_add,
561562
&compensation_xx_add, &compensation_xxx_add)
562563

@@ -566,13 +567,13 @@ def roll_skew(ndarray[float64_t] values, ndarray[int64_t] start,
566567
# and removed
567568
# calculate deletes
568569
for j in range(start[i - 1], s):
569-
val = values[j]
570+
val = values_copy[j]
570571
remove_skew(val, &nobs, &x, &xx, &xxx, &compensation_x_remove,
571572
&compensation_xx_remove, &compensation_xxx_remove)
572573

573574
# calculate adds
574575
for j in range(end[i - 1], e):
575-
val = values[j]
576+
val = values_copy[j]
576577
add_skew(val, &nobs, &x, &xx, &xxx, &compensation_x_add,
577578
&compensation_xx_add, &compensation_xxx_add)
578579

@@ -703,19 +704,20 @@ def roll_kurt(ndarray[float64_t] values, ndarray[int64_t] start,
703704
float64_t compensation_x_remove = 0, compensation_x_add = 0
704705
float64_t x = 0, xx = 0, xxx = 0, xxxx = 0
705706
int64_t nobs = 0, i, j, s, e, N = len(values), nobs_mean = 0
706-
ndarray[float64_t] output
707+
ndarray[float64_t] output, values_copy
707708
bint is_monotonic_increasing_bounds
708709

709710
minp = max(minp, 4)
710711
is_monotonic_increasing_bounds = is_monotonic_increasing_start_end_bounds(
711712
start, end
712713
)
713714
output = np.empty(N, dtype=float)
715+
values_copy = np.copy(values)
714716
min_val = np.nanmin(values)
715717

716718
with nogil:
717719
for i in range(0, N):
718-
val = values[i]
720+
val = values_copy[i]
719721
if notnan(val):
720722
nobs_mean += 1
721723
sum_val += val
@@ -724,7 +726,7 @@ def roll_kurt(ndarray[float64_t] values, ndarray[int64_t] start,
724726
if min_val - mean_val > -1e4:
725727
mean_val = round(mean_val)
726728
for i in range(0, N):
727-
values[i] = values[i] - mean_val
729+
values_copy[i] = values_copy[i] - mean_val
728730

729731
for i in range(0, N):
730732

@@ -736,7 +738,7 @@ def roll_kurt(ndarray[float64_t] values, ndarray[int64_t] start,
736738
if i == 0 or not is_monotonic_increasing_bounds:
737739

738740
for j in range(s, e):
739-
add_kurt(values[j], &nobs, &x, &xx, &xxx, &xxxx,
741+
add_kurt(values_copy[j], &nobs, &x, &xx, &xxx, &xxxx,
740742
&compensation_x_add, &compensation_xx_add,
741743
&compensation_xxx_add, &compensation_xxxx_add)
742744

@@ -746,13 +748,13 @@ def roll_kurt(ndarray[float64_t] values, ndarray[int64_t] start,
746748
# and removed
747749
# calculate deletes
748750
for j in range(start[i - 1], s):
749-
remove_kurt(values[j], &nobs, &x, &xx, &xxx, &xxxx,
751+
remove_kurt(values_copy[j], &nobs, &x, &xx, &xxx, &xxxx,
750752
&compensation_x_remove, &compensation_xx_remove,
751753
&compensation_xxx_remove, &compensation_xxxx_remove)
752754

753755
# calculate adds
754756
for j in range(end[i - 1], e):
755-
add_kurt(values[j], &nobs, &x, &xx, &xxx, &xxxx,
757+
add_kurt(values_copy[j], &nobs, &x, &xx, &xxx, &xxxx,
756758
&compensation_x_add, &compensation_xx_add,
757759
&compensation_xxx_add, &compensation_xxxx_add)
758760

pandas/tests/window/test_rolling.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -1102,11 +1102,13 @@ def test_groupby_rolling_nan_included():
11021102

11031103
@pytest.mark.parametrize("method", ["skew", "kurt"])
11041104
def test_rolling_skew_kurt_numerical_stability(method):
1105-
# GH: 6929
1106-
s = Series(np.random.rand(10))
1107-
expected = getattr(s.rolling(3), method)()
1108-
s = s + 50000
1109-
result = getattr(s.rolling(3), method)()
1105+
# GH#6929
1106+
ser = Series(np.random.rand(10))
1107+
ser_copy = ser.copy()
1108+
expected = getattr(ser.rolling(3), method)()
1109+
tm.assert_series_equal(ser, ser_copy)
1110+
ser = ser + 50000
1111+
result = getattr(ser.rolling(3), method)()
11101112
tm.assert_series_equal(result, expected)
11111113

11121114

0 commit comments

Comments
 (0)