Skip to content

Commit e08d088

Browse files
mzeitlin11feefladder
authored andcommitted
REGR: window ewm slowdown (pandas-dev#43052)
1 parent f3110ce commit e08d088

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

doc/source/whatsnew/v1.3.3.rst

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ including other versions of pandas.
1414

1515
Fixed regressions
1616
~~~~~~~~~~~~~~~~~
17+
- Performance regression in :meth:`core.window.ewm.ExponentialMovingWindow.mean` (:issue:`42333`)
1718
-
1819
-
1920

pandas/_libs/window/aggregations.pyx

+14-6
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,7 @@ def roll_weighted_var(const float64_t[:] values, const float64_t[:] weights,
14891489

14901490
def ewma(const float64_t[:] vals, const int64_t[:] start, const int64_t[:] end,
14911491
int minp, float64_t com, bint adjust, bint ignore_na,
1492-
const float64_t[:] deltas) -> np.ndarray:
1492+
const float64_t[:] deltas=None) -> np.ndarray:
14931493
"""
14941494
Compute exponentially-weighted moving average using center-of-mass.
14951495

@@ -1502,7 +1502,8 @@ def ewma(const float64_t[:] vals, const int64_t[:] start, const int64_t[:] end,
15021502
com : float64
15031503
adjust : bool
15041504
ignore_na : bool
1505-
deltas : ndarray (float64 type)
1505+
deltas : ndarray (float64 type), optional. If None, implicitly assumes equally
1506+
spaced points (used when `times` is not passed)
15061507

15071508
Returns
15081509
-------
@@ -1511,14 +1512,17 @@ def ewma(const float64_t[:] vals, const int64_t[:] start, const int64_t[:] end,
15111512

15121513
cdef:
15131514
Py_ssize_t i, j, s, e, nobs, win_size, N = len(vals), M = len(start)
1514-
const float64_t[:] sub_deltas, sub_vals
1515+
const float64_t[:] sub_vals
1516+
const float64_t[:] sub_deltas=None
15151517
ndarray[float64_t] sub_output, output = np.empty(N, dtype=np.float64)
15161518
float64_t alpha, old_wt_factor, new_wt, weighted_avg, old_wt, cur
1517-
bint is_observation
1519+
bint is_observation, use_deltas
15181520

15191521
if N == 0:
15201522
return output
15211523

1524+
use_deltas = deltas is not None
1525+
15221526
alpha = 1. / (1. + com)
15231527
old_wt_factor = 1. - alpha
15241528
new_wt = 1. if adjust else alpha
@@ -1529,7 +1533,8 @@ def ewma(const float64_t[:] vals, const int64_t[:] start, const int64_t[:] end,
15291533
sub_vals = vals[s:e]
15301534
# note that len(deltas) = len(vals) - 1 and deltas[i] is to be used in
15311535
# conjunction with vals[i+1]
1532-
sub_deltas = deltas[s:e - 1]
1536+
if use_deltas:
1537+
sub_deltas = deltas[s:e - 1]
15331538
win_size = len(sub_vals)
15341539
sub_output = np.empty(win_size, dtype=np.float64)
15351540

@@ -1547,7 +1552,10 @@ def ewma(const float64_t[:] vals, const int64_t[:] start, const int64_t[:] end,
15471552
if weighted_avg == weighted_avg:
15481553

15491554
if is_observation or not ignore_na:
1550-
old_wt *= old_wt_factor ** sub_deltas[i - 1]
1555+
if use_deltas:
1556+
old_wt *= old_wt_factor ** sub_deltas[i - 1]
1557+
else:
1558+
old_wt *= old_wt_factor
15511559
if is_observation:
15521560

15531561
# avoid numerical errors on constant series

pandas/core/window/ewm.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -474,12 +474,14 @@ def mean(self, *args, engine=None, engine_kwargs=None, **kwargs):
474474
if engine_kwargs is not None:
475475
raise ValueError("cython engine does not accept engine_kwargs")
476476
nv.validate_window_func("mean", args, kwargs)
477+
478+
deltas = None if self.times is None else self._deltas
477479
window_func = partial(
478480
window_aggregations.ewma,
479481
com=self._com,
480482
adjust=self.adjust,
481483
ignore_na=self.ignore_na,
482-
deltas=self._deltas,
484+
deltas=deltas,
483485
)
484486
return self._apply(window_func)
485487
else:

0 commit comments

Comments
 (0)