Skip to content

Commit 9821b77

Browse files
Shivam Ranajreback
Shivam Rana
authored andcommitted
BUG: pd.Series.interpolate non-numeric index column (21662) (#25394)
1 parent fd6681e commit 9821b77

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed

Diff for: doc/source/whatsnew/v0.25.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ Numeric
222222
- Bug in :meth:`to_numeric` in which numbers were being coerced to float, even though ``errors`` was not ``coerce`` (:issue:`24910`)
223223
- Bug in error messages in :meth:`DataFrame.corr` and :meth:`Series.corr`. Added the possibility of using a callable. (:issue:`25729`)
224224
- Bug in :meth:`Series.divmod` and :meth:`Series.rdivmod` which would raise an (incorrect) ``ValueError`` rather than return a pair of :class:`Series` objects as result (:issue:`25557`)
225-
-
225+
- Raises a helpful exception when a non-numeric index is sent to :meth:`interpolate` with methods which require numeric index. (:issue:`21662`)
226226
-
227227
-
228228

Diff for: pandas/core/generic.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
from pandas.core.dtypes.cast import maybe_promote, maybe_upcast_putmask
2828
from pandas.core.dtypes.common import (
2929
ensure_int64, ensure_object, is_bool, is_bool_dtype,
30-
is_datetime64_any_dtype, is_datetime64tz_dtype, is_dict_like,
31-
is_extension_array_dtype, is_integer, is_list_like, is_number,
32-
is_numeric_dtype, is_object_dtype, is_period_arraylike, is_re_compilable,
33-
is_scalar, is_timedelta64_dtype, pandas_dtype)
30+
is_datetime64_any_dtype, is_datetime64_dtype, is_datetime64tz_dtype,
31+
is_dict_like, is_extension_array_dtype, is_integer, is_list_like,
32+
is_number, is_numeric_dtype, is_object_dtype, is_period_arraylike,
33+
is_re_compilable, is_scalar, is_timedelta64_dtype, pandas_dtype)
3434
from pandas.core.dtypes.generic import ABCDataFrame, ABCPanel, ABCSeries
3535
from pandas.core.dtypes.inference import is_hashable
3636
from pandas.core.dtypes.missing import isna, notna
@@ -6865,6 +6865,18 @@ def interpolate(self, method='linear', axis=0, limit=None, inplace=False,
68656865
index = np.arange(len(_maybe_transposed_self._get_axis(alt_ax)))
68666866
else:
68676867
index = _maybe_transposed_self._get_axis(alt_ax)
6868+
methods = {"index", "values", "nearest", "time"}
6869+
is_numeric_or_datetime = (
6870+
is_numeric_dtype(index) or
6871+
is_datetime64_dtype(index) or
6872+
is_timedelta64_dtype(index)
6873+
)
6874+
if method not in methods and not is_numeric_or_datetime:
6875+
raise ValueError(
6876+
"Index column must be numeric or datetime type when "
6877+
"using {method} method other than linear. "
6878+
"Try setting a numeric or datetime index column before "
6879+
"interpolating.".format(method=method))
68686880

68696881
if isna(index).any():
68706882
raise NotImplementedError("Interpolation with NaNs in the index "

Diff for: pandas/tests/series/test_missing.py

+68
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,22 @@ def nontemporal_method(request):
870870
return method, kwargs
871871

872872

873+
@pytest.fixture(params=['linear', 'slinear', 'zero', 'quadratic', 'cubic',
874+
'barycentric', 'krogh', 'polynomial', 'spline',
875+
'piecewise_polynomial', 'from_derivatives', 'pchip',
876+
'akima', ])
877+
def interp_methods_ind(request):
878+
""" Fixture that returns a (method name, required kwargs) pair to
879+
be tested for various Index types.
880+
881+
This fixture does not include methods - 'time', 'index', 'nearest',
882+
'values' as a parameterization
883+
"""
884+
method = request.param
885+
kwargs = dict(order=1) if method in ('spline', 'polynomial') else dict()
886+
return method, kwargs
887+
888+
873889
class TestSeriesInterpolateData():
874890
def test_interpolate(self, datetime_series, string_series):
875891
ts = Series(np.arange(len(datetime_series), dtype=float),
@@ -1397,3 +1413,55 @@ def test_nonzero_warning(self):
13971413
ser = pd.Series([1, 0, 3, 4])
13981414
with tm.assert_produces_warning(FutureWarning):
13991415
ser.nonzero()
1416+
1417+
@pytest.mark.parametrize(
1418+
"ind",
1419+
[
1420+
['a', 'b', 'c', 'd'],
1421+
pd.period_range(start="2019-01-01", periods=4),
1422+
pd.interval_range(start=0, end=4),
1423+
])
1424+
def test_interp_non_timedelta_index(self, interp_methods_ind, ind):
1425+
# gh 21662
1426+
df = pd.DataFrame([0, 1, np.nan, 3], index=ind)
1427+
1428+
method, kwargs = interp_methods_ind
1429+
if method == "pchip":
1430+
_skip_if_no_pchip()
1431+
1432+
if method == "linear":
1433+
result = df[0].interpolate(**kwargs)
1434+
expected = pd.Series([0.0, 1.0, 2.0, 3.0], name=0, index=ind)
1435+
assert_series_equal(result, expected)
1436+
else:
1437+
expected_error = (
1438+
"Index column must be numeric or datetime type when "
1439+
"using {method} method other than linear. "
1440+
"Try setting a numeric or datetime index column before "
1441+
"interpolating.".format(method=method))
1442+
with pytest.raises(ValueError, match=expected_error):
1443+
df[0].interpolate(method=method, **kwargs)
1444+
1445+
def test_interpolate_timedelta_index(self, interp_methods_ind):
1446+
"""
1447+
Tests for non numerical index types - object, period, timedelta
1448+
Note that all methods except time, index, nearest and values
1449+
are tested here.
1450+
"""
1451+
# gh 21662
1452+
ind = pd.timedelta_range(start=1, periods=4)
1453+
df = pd.DataFrame([0, 1, np.nan, 3], index=ind)
1454+
1455+
method, kwargs = interp_methods_ind
1456+
if method == "pchip":
1457+
_skip_if_no_pchip()
1458+
1459+
if method in {"linear", "pchip"}:
1460+
result = df[0].interpolate(method=method, **kwargs)
1461+
expected = pd.Series([0.0, 1.0, 2.0, 3.0], name=0, index=ind)
1462+
assert_series_equal(result, expected)
1463+
else:
1464+
pytest.skip(
1465+
"This interpolation method is not supported for "
1466+
"Timedelta Index yet."
1467+
)

0 commit comments

Comments
 (0)