Skip to content

Commit 8743be5

Browse files
committed
BUG: treat nobs=1 >= min_periods case in rolling_std/variance as 0 trivially. close #1884
1 parent 66a1637 commit 8743be5

File tree

4 files changed

+21
-3
lines changed

4 files changed

+21
-3
lines changed

RELEASE.rst

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ pandas 0.9.0
154154
- Respect passed color keyword argument in Series.plot (#1890)
155155
- Fix rolling_min/max when the window is larger than the size of the input
156156
array. Check other malformed inputs (#1899, #1897)
157+
- Rolling variance / standard deviation with only a single observation in
158+
window (#1884)
157159

158160
pandas 0.8.1
159161
============

pandas/src/moments.pyx

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
def _check_minp(win, minp, N):
1313
if minp > win:
14-
raise ValueError('min_periods %d must be <= window %d'
14+
raise ValueError('min_periods (%d) must be <= window (%d)'
1515
% (minp, win))
1616
elif minp > N:
1717
minp = N + 1
@@ -382,6 +382,11 @@ def roll_var(ndarray[double_t] input, int win, int minp, int ddof=1):
382382
sum_xx += val * val
383383

384384
if nobs >= minp:
385+
# pathological case
386+
if nobs == 1:
387+
output[i] = 0
388+
continue
389+
385390
output[i] = (nobs * sum_xx - sum_x * sum_x) / (nobs * (nobs - ddof))
386391
else:
387392
output[i] = NaN

pandas/stats/moments.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,9 @@ def call_cython(arg, window, minp, **kwds):
447447

448448
_ts_std = lambda *a, **kw: _zsqrt(lib.roll_var(*a, **kw))
449449
rolling_std = _rolling_func(_ts_std, 'Unbiased moving standard deviation',
450-
check_minp=_require_min_periods(2))
450+
check_minp=_require_min_periods(1))
451451
rolling_var = _rolling_func(lib.roll_var, 'Unbiased moving variance',
452-
check_minp=_require_min_periods(2))
452+
check_minp=_require_min_periods(1))
453453
rolling_skew = _rolling_func(lib.roll_skew, 'Unbiased moving skewness',
454454
check_minp=_require_min_periods(3))
455455
rolling_kurt = _rolling_func(lib.roll_kurt, 'Unbiased moving kurtosis',

pandas/stats/tests/test_moments.py

+11
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,17 @@ def test_rolling_std(self):
112112
self._check_moment_func(functools.partial(mom.rolling_std, ddof=0),
113113
lambda x: np.std(x, ddof=0))
114114

115+
def test_rolling_std_1obs(self):
116+
result = mom.rolling_std(np.array([1.,2.,3.,4.,5.]),
117+
1, min_periods=1)
118+
expected = np.zeros(5)
119+
120+
assert_almost_equal(result, expected)
121+
122+
result = mom.rolling_std(np.array([np.nan,np.nan,3.,4.,5.]),
123+
3, min_periods=2)
124+
self.assert_(np.isnan(result[2]))
125+
115126
def test_rolling_std_neg_sqrt(self):
116127
# unit test from Bottleneck
117128

0 commit comments

Comments
 (0)