@@ -148,12 +148,17 @@ def rolling_count(arg, window, freq=None, center=False, time_rule=None):
148
148
return_hook , values = _process_data_structure (arg , kill_inf = False )
149
149
150
150
converted = np .isfinite (values ).astype (float )
151
- result = rolling_sum (converted , window , min_periods = 1 ,
152
- center = center ) # already converted
151
+ if center :
152
+ center = ('na' ,'na' )
153
+ converted = _center_window (converted , window , 0 , center = center )
154
+ result = rolling_sum (converted , window , min_periods = 1 ,
155
+ center = False )
156
+ else :
153
157
154
- # putmask here?
155
- result [ np . isnan ( result )] = 0
158
+ result = rolling_sum ( converted , window , min_periods = 1 ,
159
+ center = center )
156
160
161
+ result [np .isnan (result )] = 0
157
162
return return_hook (result )
158
163
159
164
@@ -277,50 +282,58 @@ def _rolling_moment(arg, window, func, minp, axis=0, freq=None,
277
282
y : type of input
278
283
"""
279
284
arg = _conv_timerule (arg , freq , time_rule )
280
- calc = lambda x : func (x , window , minp = minp , ** kwargs )
281
285
return_hook , values = _process_data_structure (arg )
286
+
282
287
# actually calculate the moment. Faster way to do this?
283
- if values .ndim > 1 :
284
- result = np .apply_along_axis (calc , axis , values )
285
- else :
286
- result = calc (values )
288
+ def calc (x ):
289
+ _calc = lambda x : func (x , window , minp = minp , ** kwargs )
290
+ if x .ndim > 1 :
291
+ return np .apply_along_axis (_calc , axis , x )
292
+ else :
293
+ return _calc (x )
287
294
295
+ result = calc (values )
288
296
rs = return_hook (result )
289
297
if center :
290
- rs = _center_window (rs , window , axis )
298
+ rs = _center_window (rs , window , axis , center = center )
291
299
# GH2953, fixup edges
292
300
if window > 2 :
293
- if values .ndim > 1 :
294
- # TODO: handle mi vectorized case
295
- pass
301
+
302
+ # there's an ambiguity on what constitutes
303
+ # the "center" when window is even
304
+ # we Just close ranks with numpy , see test case
305
+ # delta = 1 if window % 2 == 0 else 0
306
+ if window % 2 == 0 :
307
+ nahead = (window - 1 )// 2 or 1
296
308
else :
297
- # there's an ambiguity on what constitutes
298
- # the "center" when window is even
299
- # we Just close ranks with numpy , see test case
300
- # delta = 1 if window % 2 == 0 else 0
301
- if window % 2 == 0 :
302
- nahead = (window - 1 )// 2 or 1
303
- else :
304
- nahead = (window )// 2
305
-
306
- # fixup the head
307
- tip = np .append (np .zeros (nahead + 1 ),values [:(2 * nahead + 1 )])
308
- rs [:nahead + 1 ] = calc (tip )[- (nahead + 1 ):][:nahead + 1 ]
309
-
310
- # fixup the tail
311
- tip = np .append (values [- (2 * nahead + 1 ):],np .zeros (nahead ))
312
- rs [- (nahead ):] = calc (tip )[- (nahead ):]
313
-
314
- if minp > 0 :
315
- d = minp - nahead - 1
316
- if d > 0 :
317
- rs [:d ] = NaN
318
- rs [- (d ):] = NaN
309
+ nahead = (window )// 2
310
+
311
+ # fixup the head
312
+ shape = list (values .shape )
313
+ shape [0 ] = nahead + 1
314
+ tip = np .append (np .zeros (tuple (shape )),values [:(2 * nahead + 1 )],axis = 0 )
315
+ rs [:nahead + 1 ] = calc (tip )[- (nahead + 1 ):][:nahead + 1 ]
316
+ if minp > 0 :
317
+ d = max (minp ,nahead + 1 )
318
+ if d > 0 :
319
+ rs [:d ] = NaN
320
+
321
+
322
+ # fixup the tail
323
+ shape = list (values .shape )
324
+ shape [0 ] = nahead
325
+ tip = np .append (values [- (2 * nahead + 1 ):],np .zeros (tuple (shape )),axis = 0 )
326
+ rs [- (nahead ):] = calc (tip )[- (nahead ):]
327
+
328
+ if minp > 0 :
329
+ d = max (nahead ,minp )
330
+ if d > 0 :
331
+ rs [- d :] = NaN
319
332
320
333
return rs
321
334
322
335
323
- def _center_window (rs , window , axis ):
336
+ def _center_window (rs , window , axis , center = None ):
324
337
offset = int ((window - 1 ) / 2. )
325
338
if isinstance (rs , (Series , DataFrame , Panel )):
326
339
rs = rs .shift (- offset , axis = axis )
@@ -335,7 +348,23 @@ def _center_window(rs, window, axis):
335
348
na_indexer [axis ] = slice (- offset , None )
336
349
337
350
rs [tuple (rs_indexer )] = np .copy (rs [tuple (lead_indexer )])
351
+
352
+ # center can optionally point to an action on
353
+ # lhs or rhs
354
+
355
+ if not isinstance (center , tuple ):
356
+ center = ('copy' ,'na' )
357
+ lhs , rhs = center
358
+
359
+ # lhs : default is copy
360
+ if lhs == 'na' :
361
+ lhs_indexer = [slice (None )] * rs .ndim
362
+ lhs_indexer [axis ] = slice (0 , offset + 1 )
363
+ rs [tuple (lhs_indexer )] = np .nan
364
+
365
+ # rhs : default is na
338
366
rs [tuple (na_indexer )] = np .nan
367
+
339
368
return rs
340
369
341
370
0 commit comments