25
25
# Series: Prentice-Hall Series in Automatic Computation
26
26
27
27
28
- def kth_smallest (ndarray[double_t , ndim = 1 ] a, Py_ssize_t k ):
28
+ def kth_smallest (ndarray[double_t] a , Py_ssize_t k ):
29
29
cdef:
30
30
Py_ssize_t i,j,l,m,n
31
31
double_t x, t
@@ -82,8 +82,7 @@ def roll_sum(ndarray[double_t] input, int win, int minp):
82
82
83
83
cdef ndarray[double_t] output = np.empty(N, dtype = float )
84
84
85
- if minp > N:
86
- minp = N + 1
85
+ minp = _check_minp(minp, N)
87
86
88
87
for i from 0 <= i < minp - 1 :
89
88
val = input [i]
@@ -126,8 +125,7 @@ def roll_mean(ndarray[double_t] input,
126
125
127
126
cdef ndarray[double_t] output = np.empty(N, dtype = float )
128
127
129
- if minp > N:
130
- minp = N + 1
128
+ minp = _check_minp(minp, N)
131
129
132
130
for i from 0 <= i < minp - 1 :
133
131
val = input [i]
@@ -213,15 +211,23 @@ def ewma(ndarray[double_t] input, double_t com):
213
211
# -------------------------------------------------------------------------------
214
212
# Rolling variance
215
213
214
+ def _check_minp (minp , N ):
215
+ if minp > N:
216
+ minp = N + 1
217
+ elif minp == 0 :
218
+ minp = 1
219
+ elif minp < 0 :
220
+ raise ValueError (' min_periods must be >= 0' )
221
+ return minp
222
+
216
223
def roll_var (ndarray[double_t] input , int win , int minp ):
217
224
cdef double val, prev, sum_x = 0 , sum_xx = 0 , nobs = 0
218
225
cdef Py_ssize_t i
219
226
cdef Py_ssize_t N = len (input )
220
227
221
228
cdef ndarray[double_t] output = np.empty(N, dtype = float )
222
229
223
- if minp > N:
224
- minp = N + 1
230
+ minp = _check_minp(minp, N)
225
231
226
232
for i from 0 <= i < minp - 1 :
227
233
val = input [i]
@@ -270,8 +276,7 @@ def roll_skew(ndarray[double_t] input, int win, int minp):
270
276
# 3 components of the skewness equation
271
277
cdef double A, B, C, R
272
278
273
- if minp > N:
274
- minp = N + 1
279
+ minp = _check_minp(minp, N)
275
280
276
281
for i from 0 <= i < minp - 1 :
277
282
val = input [i]
@@ -333,8 +338,7 @@ def roll_kurt(ndarray[double_t] input,
333
338
# 5 components of the kurtosis equation
334
339
cdef double A, B, C, D, R, K
335
340
336
- if minp > N:
337
- minp = N + 1
341
+ minp = _check_minp(minp, N)
338
342
339
343
for i from 0 <= i < minp - 1 :
340
344
val = input [i]
@@ -405,8 +409,7 @@ cdef _roll_skiplist_op(ndarray arg, int win, int minp, skiplist_f op):
405
409
406
410
skiplist = IndexableSkiplist(win)
407
411
408
- if minp > N:
409
- minp = N + 1
412
+ minp = _check_minp(minp, N)
410
413
411
414
for i from 0 <= i < minp - 1 :
412
415
val = input [i]
@@ -484,51 +487,50 @@ cdef double_t _get_min(object skiplist, int nobs, int minp):
484
487
485
488
def roll_quantile (ndarray[float64_t , cast = True ] input , int win ,
486
489
int minp , double quantile ):
487
- '''
488
- O(N log(window)) implementation using skip list
489
- '''
490
- cdef double val, prev, midpoint
491
- cdef IndexableSkiplist skiplist
492
- cdef Py_ssize_t nobs = 0 , i
493
- cdef Py_ssize_t N = len (input )
494
- cdef ndarray[double_t] output = np.empty(N, dtype = float )
490
+ '''
491
+ O(N log(window)) implementation using skip list
492
+ '''
493
+ cdef double val, prev, midpoint
494
+ cdef IndexableSkiplist skiplist
495
+ cdef Py_ssize_t nobs = 0 , i
496
+ cdef Py_ssize_t N = len (input )
497
+ cdef ndarray[double_t] output = np.empty(N, dtype = float )
495
498
496
- skiplist = IndexableSkiplist(win)
499
+ skiplist = IndexableSkiplist(win)
497
500
498
- if minp > N:
499
- minp = N + 1
501
+ minp = _check_minp(minp, N)
500
502
501
- for i from 0 <= i < minp - 1 :
502
- val = input [i]
503
+ for i from 0 <= i < minp - 1 :
504
+ val = input [i]
503
505
504
- # Not NaN
505
- if val == val:
506
- nobs += 1
507
- skiplist.insert(val)
506
+ # Not NaN
507
+ if val == val:
508
+ nobs += 1
509
+ skiplist.insert(val)
508
510
509
- output[i] = NaN
511
+ output[i] = NaN
510
512
511
- for i from minp - 1 <= i < N:
512
- val = input [i]
513
+ for i from minp - 1 <= i < N:
514
+ val = input [i]
513
515
514
- if i > win - 1 :
515
- prev = input [i - win]
516
+ if i > win - 1 :
517
+ prev = input [i - win]
516
518
517
- if prev == prev:
518
- skiplist.remove(prev)
519
- nobs -= 1
519
+ if prev == prev:
520
+ skiplist.remove(prev)
521
+ nobs -= 1
520
522
521
- if val == val:
522
- nobs += 1
523
- skiplist.insert(val)
523
+ if val == val:
524
+ nobs += 1
525
+ skiplist.insert(val)
524
526
525
- if nobs >= minp:
526
- idx = int ((quantile / 1. ) * (nobs - 1 ))
527
- output[i] = skiplist.get(idx)
528
- else :
529
- output[i] = NaN
527
+ if nobs >= minp:
528
+ idx = int ((quantile / 1. ) * (nobs - 1 ))
529
+ output[i] = skiplist.get(idx)
530
+ else :
531
+ output[i] = NaN
530
532
531
- return output
533
+ return output
532
534
533
535
def roll_generic (ndarray[float64_t , cast = True ] input , int win ,
534
536
int minp , object func ):
@@ -542,6 +544,7 @@ def roll_generic(ndarray[float64_t, cast=True] input, int win,
542
544
buf = < float64_t* > input .data
543
545
544
546
n = len (input )
547
+ minp = _check_minp(minp, n)
545
548
output = np.empty(n, dtype = float )
546
549
counts = roll_sum(np.isfinite(input ).astype(float ), win, minp)
547
550
0 commit comments