@@ -1284,10 +1284,8 @@ def roll_cov(ndarray[double_t] x, ndarray[double_t] y, int win, int minp,
12841284
12851285 if val_not_nan:
12861286 # Adding one observation...
1287- nobs += 1
12881287 if prev_not_nan:
12891288 # ...and removing another
1290- nobs -= 1
12911289 delta_x = val_x - prev_x
12921290 prev_x -= mean_x
12931291 mean_x += delta_x / nobs
@@ -1299,6 +1297,7 @@ def roll_cov(ndarray[double_t] x, ndarray[double_t] y, int win, int minp,
12991297 proddm_xy += (delta_x * (val_y + prev_y) + delta_y * (val_x + prev_x)) / 2
13001298 else :
13011299 # ...and not removing any
1300+ nobs += 1
13021301 delta_x = val_x - mean_x
13031302 mean_x += delta_x / nobs
13041303 delta_y = val_y - mean_y
@@ -1335,84 +1334,51 @@ def roll_var(ndarray[double_t] input, int win, int minp, int ddof=1):
13351334 """
13361335 Numerically stable implementation using Welford's method.
13371336 """
1338- cdef double val, prev, mean_x = 0 , ssqdm_x = 0 , nobs = 0 , delta
1337+ cdef double val, prev, mean_x = 0 , ssqdm_x = 0 , nobs = 0 , delta, out
13391338 cdef Py_ssize_t i
13401339 cdef Py_ssize_t N = len (input )
13411340
13421341 cdef ndarray[double_t] output = np.empty(N, dtype = float )
13431342
13441343 minp = _check_minp(win, minp, N)
13451344
1346- # Check for windows larger than array, addresses #7297
1347- win = min (win, N)
1348-
1349- # Over the first window, observations can only be added, never removed
1350- for i from 0 <= i < win:
1351- val = input [i]
1352-
1353- # Not NaN
1354- if val == val:
1355- nobs += 1
1356- delta = (val - mean_x)
1357- mean_x += delta / nobs
1358- ssqdm_x += delta * (val - mean_x)
1359-
1360- if (nobs >= minp) and (nobs > ddof):
1361- # pathological case
1362- if nobs == 1 :
1363- val = 0
1364- else :
1365- val = ssqdm_x / (nobs - ddof)
1366- if val < 0 :
1367- val = 0
1368- else :
1369- val = NaN
1370-
1371- output[i] = val
1372-
1373- # After the first window, observations can both be added and removed
1374- for i from win <= i < N:
1345+ for i from 0 <= i < N:
13751346 val = input [i]
1376- prev = input [i - win]
1347+ prev = NaN if i < win else input [i - win]
13771348
13781349 if val == val:
1350+ # Adding one observation...
13791351 if prev == prev:
1380- # Adding one observation and removing another one
1381- delta = val - prev
1352+ # ... and removing another
1353+ delta val - prev
13821354 prev -= mean_x
13831355 mean_x += delta / nobs
13841356 val -= mean_x
13851357 ssqdm_x += (val + prev) * delta
13861358 else :
13871359 # Adding one observation and not removing any
13881360 nobs += 1
1389- delta = ( val - mean_x)
1361+ delta = val - mean_x
13901362 mean_x += delta / nobs
13911363 ssqdm_x += delta * (val - mean_x)
13921364 elif prev == prev:
1393- # Adding no new observation, but removing one
1365+ # adding no new observation, but removing one
13941366 nobs -= 1
13951367 if nobs:
1396- delta = ( prev - mean_x)
1397- mean_x -= delta / nobs
1368+ delta = prev - mean_x
1369+ mean_x -= delta / nobs
13981370 ssqdm_x -= delta * (prev - mean_x)
13991371 else :
1400- mean_x = 0
1401- ssqdm_x = 0
1372+ mean_x = ssqdm_x = 0
14021373 # Variance is unchanged if no observation is added or removed
14031374
1404- if (nobs >= minp) and (nobs > ddof):
1405- # pathological case
1406- if nobs == 1 :
1407- val = 0
1408- else :
1409- val = ssqdm_x / (nobs - ddof)
1410- if val < 0 :
1411- val = 0
1375+ if nobs >= minp and nobs > ddof:
1376+ out = ssqdm_x / (nobs - ddof)
1377+ out = 0 if out < 0 else out
14121378 else :
1413- val = NaN
1379+ out = NaN
14141380
1415- output[i] = val
1381+ output[i] = out
14161382
14171383 return output
14181384
0 commit comments