Repository: pandas-dev/pandas

Issue:
series.interpolate() corner cases
from the [pydata mailing list](https://groups.google.com/forum/?fromgroups#!topic/pydata/40-Yj9R0LJ4)

I've been using Series.interpolate(), and have noticed that, while it
leaves NaN entries alone if they precede a non-null value, it blows up if
there are no non-null entries. Wouldn't it make more sense just to leave
completely null series alone (so the user doesn't have to manually check
for this case)? Here's an example:

1) This one works:

``` python
S1 = Series([np.nan, 2.0])
print S1.interpolate()

-------

0   NaN
1     2
dtype: float64
```

2) This one blows up:

``` python
S2 = Series([np.nan, np.nan])
print S2.interpolate()

ValueError                                Traceback (most recent call last)
<ipython-input-49-620b22122e43> in <module>()
      3
      4 S2 = Series([np.nan, np.nan])
----> 5 print S2.interpolate()

/RHS/packages/anaconda/pandas/pandas/core/series.pyc in interpolate(self,
method)
   3191         result = values.copy()
   3192         result[firstIndex:][invalid] = np.interp(inds[invalid],
inds[valid],
-> 3193
values[firstIndex:][valid])
   3194
   3195         return Series(result, index=self.index, name=self.name)

/Users/stanton/anaconda/lib/python2.7/site-packages/numpy/lib/function_base
.pyc in interp(x, xp, fp, left, right)
   1067         return compiled_interp([x], xp, fp, left, right).item()
   1068     else:
-> 1069         return compiled_interp(x, xp, fp, left, right)
   1070
   1071

ValueError: array of sample points is empty
```

3) empty series (not mentioned in the original post)

``` python
In [38]: pd.Series([]).interpolate()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-38-012633a78523> in <module>()
----> 1 pd.Series([]).interpolate()

.../pandas/core/series.pyc in interpolate(self, method)
   3184         valid = -invalid
   3185 
-> 3186         firstIndex = valid.argmax()
   3187         valid = valid[firstIndex:]
   3188         invalid = invalid[firstIndex:]

ValueError: attempt to get argmax/argmin of an empty sequence
```

series.interpolate() corner cases
from the [pydata mailing list](https://groups.google.com/forum/?fromgroups#!topic/pydata/40-Yj9R0LJ4)

I've been using Series.interpolate(), and have noticed that, while it
leaves NaN entries alone if they precede a non-null value, it blows up if
there are no non-null entries. Wouldn't it make more sense just to leave
completely null series alone (so the user doesn't have to manually check
for this case)? Here's an example:

1) This one works:

``` python
S1 = Series([np.nan, 2.0])
print S1.interpolate()

-------

0   NaN
1     2
dtype: float64
```

2) This one blows up:

``` python
S2 = Series([np.nan, np.nan])
print S2.interpolate()

ValueError                                Traceback (most recent call last)
<ipython-input-49-620b22122e43> in <module>()
      3
      4 S2 = Series([np.nan, np.nan])
----> 5 print S2.interpolate()

/RHS/packages/anaconda/pandas/pandas/core/series.pyc in interpolate(self,
method)
   3191         result = values.copy()
   3192         result[firstIndex:][invalid] = np.interp(inds[invalid],
inds[valid],
-> 3193
values[firstIndex:][valid])
   3194
   3195         return Series(result, index=self.index, name=self.name)

/Users/stanton/anaconda/lib/python2.7/site-packages/numpy/lib/function_base
.pyc in interp(x, xp, fp, left, right)
   1067         return compiled_interp([x], xp, fp, left, right).item()
   1068     else:
-> 1069         return compiled_interp(x, xp, fp, left, right)
   1070
   1071

ValueError: array of sample points is empty
```

3) empty series (not mentioned in the original post)

``` python
In [38]: pd.Series([]).interpolate()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-38-012633a78523> in <module>()
----> 1 pd.Series([]).interpolate()

.../pandas/core/series.pyc in interpolate(self, method)
   3184         valid = -invalid
   3185 
-> 3186         firstIndex = valid.argmax()
   3187         valid = valid[firstIndex:]
   3188         invalid = invalid[firstIndex:]

ValueError: attempt to get argmax/argmin of an empty sequence
```



Discussion:
@lodagro want to do a PR for this?

@jreback how can i refuse :-) ... probably not too much work, throw in a check somewhere for no NaN data. It won`t be in the next days though. btw are you and @y-p on pandas payroll? Your contribution is just crazy.

hahah....just for fun!

thanks

@lodagro want to do a PR for this?

@jreback how can i refuse :-) ... probably not too much work, throw in a check somewhere for no NaN data. It won`t be in the next days though. btw are you and @y-p on pandas payroll? Your contribution is just crazy.

hahah....just for fun!

thanks


Resolving patch:
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -3180,14 +3180,15 @@ def interpolate(self, method='linear'):
         invalid = isnull(values)
         valid = -invalid
 
-        firstIndex = valid.argmax()
-        valid = valid[firstIndex:]
-        invalid = invalid[firstIndex:]
-        inds = inds[firstIndex:]
-
         result = values.copy()
-        result[firstIndex:][invalid] = np.interp(inds[invalid], inds[valid],
-                                                 values[firstIndex:][valid])
+        if valid.any():
+            firstIndex = valid.argmax()
+            valid = valid[firstIndex:]
+            invalid = invalid[firstIndex:]
+            inds = inds[firstIndex:]
+
+            result[firstIndex:][invalid] = np.interp(
+                inds[invalid], inds[valid], values[firstIndex:][valid])
 
         return Series(result, index=self.index, name=self.name)
 


Test patch:
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -4063,6 +4063,13 @@ def test_interpolate(self):
         # try time interpolation on a non-TimeSeries
         self.assertRaises(Exception, self.series.interpolate, method='time')
 
+    def test_interpolate_corners(self):
+        s = Series([np.nan, np.nan])
+        assert_series_equal(s.interpolate(), s)
+
+        s = Series([]).interpolate()
+        assert_series_equal(s.interpolate(), s)
+
     def test_interpolate_index_values(self):
         s = Series(np.nan, index=np.sort(np.random.rand(30)))
         s[::3] = np.random.randn(10)