@@ -1284,10 +1284,8 @@ def roll_cov(ndarray[double_t] x, ndarray[double_t] y, int win, int minp,
1284
1284
1285
1285
if val_not_nan:
1286
1286
# Adding one observation...
1287
- nobs += 1
1288
1287
if prev_not_nan:
1289
1288
# ...and removing another
1290
- nobs -= 1
1291
1289
delta_x = val_x - prev_x
1292
1290
prev_x -= mean_x
1293
1291
mean_x += delta_x / nobs
@@ -1299,6 +1297,7 @@ def roll_cov(ndarray[double_t] x, ndarray[double_t] y, int win, int minp,
1299
1297
proddm_xy += (delta_x * (val_y + prev_y) + delta_y * (val_x + prev_x)) / 2
1300
1298
else :
1301
1299
# ...and not removing any
1300
+ nobs += 1
1302
1301
delta_x = val_x - mean_x
1303
1302
mean_x += delta_x / nobs
1304
1303
delta_y = val_y - mean_y
@@ -1335,84 +1334,51 @@ def roll_var(ndarray[double_t] input, int win, int minp, int ddof=1):
1335
1334
"""
1336
1335
Numerically stable implementation using Welford's method.
1337
1336
"""
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
1339
1338
cdef Py_ssize_t i
1340
1339
cdef Py_ssize_t N = len (input )
1341
1340
1342
1341
cdef ndarray[double_t] output = np.empty(N, dtype = float )
1343
1342
1344
1343
minp = _check_minp(win, minp, N)
1345
1344
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:
1375
1346
val = input [i]
1376
- prev = input [i - win]
1347
+ prev = NaN if i < win else input [i - win]
1377
1348
1378
1349
if val == val:
1350
+ # Adding one observation...
1379
1351
if prev == prev:
1380
- # Adding one observation and removing another one
1381
- delta = val - prev
1352
+ # ... and removing another
1353
+ delta val - prev
1382
1354
prev -= mean_x
1383
1355
mean_x += delta / nobs
1384
1356
val -= mean_x
1385
1357
ssqdm_x += (val + prev) * delta
1386
1358
else :
1387
1359
# Adding one observation and not removing any
1388
1360
nobs += 1
1389
- delta = ( val - mean_x)
1361
+ delta = val - mean_x
1390
1362
mean_x += delta / nobs
1391
1363
ssqdm_x += delta * (val - mean_x)
1392
1364
elif prev == prev:
1393
- # Adding no new observation, but removing one
1365
+ # adding no new observation, but removing one
1394
1366
nobs -= 1
1395
1367
if nobs:
1396
- delta = ( prev - mean_x)
1397
- mean_x -= delta / nobs
1368
+ delta = prev - mean_x
1369
+ mean_x -= delta / nobs
1398
1370
ssqdm_x -= delta * (prev - mean_x)
1399
1371
else :
1400
- mean_x = 0
1401
- ssqdm_x = 0
1372
+ mean_x = ssqdm_x = 0
1402
1373
# Variance is unchanged if no observation is added or removed
1403
1374
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
1412
1378
else :
1413
- val = NaN
1379
+ out = NaN
1414
1380
1415
- output[i] = val
1381
+ output[i] = out
1416
1382
1417
1383
return output
1418
1384
0 commit comments