Skip to content

Commit c6110e2

Browse files
Jason Wolosonovichjreback
Jason Wolosonovich
authored andcommitted
BUG: COMPAT:0.18 added scipy version check
closes #12887 closes #13007
1 parent b25343c commit c6110e2

File tree

4 files changed

+101
-5
lines changed

4 files changed

+101
-5
lines changed

doc/source/whatsnew/v0.18.1.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ Other API changes
512512
- Provide a proper ``__name__`` and ``__qualname__`` attributes for generic functions (:issue:`12021`)
513513
- ``pd.concat(ignore_index=True)`` now uses ``RangeIndex`` as default (:issue:`12695`)
514514
- ``pd.merge()`` and ``DataFrame.join()`` will show a ``UserWarning`` when merging/joining a single- with a multi-leveled dataframe (:issue:`9455`, :issue:`12219`)
515+
- Compat with SciPy > 0.17 for deprecated ``piecewise_polynomial`` interpolation method (:issue:`12887`)
515516

516517
.. _whatsnew_0181.deprecations:
517518

pandas/core/generic.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3452,8 +3452,8 @@ def replace(self, to_replace=None, value=None, inplace=False, limit=None,
34523452
----------
34533453
method : {'linear', 'time', 'index', 'values', 'nearest', 'zero',
34543454
'slinear', 'quadratic', 'cubic', 'barycentric', 'krogh',
3455-
'polynomial', 'spline' 'piecewise_polynomial', 'pchip',
3456-
'akima'}
3455+
'polynomial', 'spline', 'piecewise_polynomial',
3456+
'from_derivatives', 'pchip', 'akima'}
34573457
34583458
* 'linear': ignore the index and treat the values as equally
34593459
spaced. This is the only method supported on MultiIndexes.
@@ -3473,9 +3473,15 @@ def replace(self, to_replace=None, value=None, inplace=False, limit=None,
34733473
the scipy documentation for more on their behavior
34743474
`here <http://docs.scipy.org/doc/scipy/reference/interpolate.html#univariate-interpolation>`__ # noqa
34753475
`and here <http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html>`__ # noqa
3476+
* 'from_derivatives' refers to BPoly.from_derivatives which
3477+
replaces 'piecewise_polynomial' interpolation method in scipy 0.18
34763478
34773479
.. versionadded:: 0.18.1
3480+
34783481
Added support for the 'akima' method
3482+
Added interpolate method 'from_derivatives' which replaces
3483+
'piecewise_polynomial' in scipy 0.18; backwards-compatible with
3484+
scipy < 0.18
34793485
34803486
axis : {0, 1}, default 0
34813487
* 0: fill column-by-column

pandas/core/missing.py

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
import numpy as np
6+
from distutils.version import LooseVersion
67

78
import pandas.core.common as com
89
import pandas.algos as algos
@@ -85,13 +86,15 @@ def clean_interp_method(method, **kwargs):
8586
order = kwargs.get('order')
8687
valid = ['linear', 'time', 'index', 'values', 'nearest', 'zero', 'slinear',
8788
'quadratic', 'cubic', 'barycentric', 'polynomial', 'krogh',
88-
'piecewise_polynomial', 'pchip', 'akima', 'spline']
89+
'piecewise_polynomial', 'pchip', 'akima', 'spline',
90+
'from_derivatives']
8991
if method in ('spline', 'polynomial') and order is None:
9092
raise ValueError("You must specify the order of the spline or "
9193
"polynomial.")
9294
if method not in valid:
9395
raise ValueError("method must be one of {0}."
9496
"Got '{1}' instead.".format(valid, method))
97+
9598
return method
9699

97100

@@ -191,7 +194,8 @@ def _interp_limit(invalid, fw_limit, bw_limit):
191194

192195
sp_methods = ['nearest', 'zero', 'slinear', 'quadratic', 'cubic',
193196
'barycentric', 'krogh', 'spline', 'polynomial',
194-
'piecewise_polynomial', 'pchip', 'akima']
197+
'from_derivatives', 'piecewise_polynomial', 'pchip', 'akima']
198+
195199
if method in sp_methods:
196200
inds = np.asarray(xvalues)
197201
# hack for DatetimeIndex, #1646
@@ -228,7 +232,8 @@ def _interpolate_scipy_wrapper(x, y, new_x, method, fill_value=None,
228232
alt_methods = {
229233
'barycentric': interpolate.barycentric_interpolate,
230234
'krogh': interpolate.krogh_interpolate,
231-
'piecewise_polynomial': interpolate.piecewise_polynomial_interpolate,
235+
'from_derivatives': _from_derivatives,
236+
'piecewise_polynomial': _from_derivatives,
232237
}
233238

234239
if getattr(x, 'is_all_dates', False):
@@ -277,6 +282,60 @@ def _interpolate_scipy_wrapper(x, y, new_x, method, fill_value=None,
277282
return new_y
278283

279284

285+
def _from_derivatives(xi, yi, x, order=None, der=0, extrapolate=False):
286+
"""
287+
Convenience function for interpolate.BPoly.from_derivatives
288+
289+
Construct a piecewise polynomial in the Bernstein basis, compatible
290+
with the specified values and derivatives at breakpoints.
291+
292+
Parameters
293+
----------
294+
xi : array_like
295+
sorted 1D array of x-coordinates
296+
yi : array_like or list of array-likes
297+
yi[i][j] is the j-th derivative known at xi[i]
298+
orders : None or int or array_like of ints. Default: None.
299+
Specifies the degree of local polynomials. If not None, some
300+
derivatives are ignored.
301+
der : int or list
302+
How many derivatives to extract; None for all potentially nonzero
303+
derivatives (that is a number equal to the number of points), or a
304+
list of derivatives to extract. This numberincludes the function
305+
value as 0th derivative.
306+
extrapolate : bool, optional
307+
Whether to extrapolate to ouf-of-bounds points based on first and last
308+
intervals, or to return NaNs. Default: True.
309+
310+
See Also
311+
--------
312+
scipy.interpolate.BPoly.from_derivatives
313+
314+
Returns
315+
-------
316+
y : scalar or array_like
317+
The result, of length R or length M or M by R,
318+
319+
"""
320+
import scipy
321+
from scipy import interpolate
322+
323+
if LooseVersion(scipy.__version__) < '0.18.0':
324+
try:
325+
method = interpolate.piecewise_polynomial_interpolate
326+
return method(xi, yi.reshape(-1, 1), x,
327+
orders=order, der=der)
328+
except AttributeError:
329+
pass
330+
331+
# return the method for compat with scipy version & backwards compat
332+
method = interpolate.BPoly.from_derivatives
333+
m = method(xi, yi.reshape(-1, 1),
334+
orders=order, extrapolate=extrapolate)
335+
336+
return m(x)
337+
338+
280339
def _akima_interpolate(xi, yi, x, der=0, axis=0):
281340
"""
282341
Convenience function for akima interpolation.

pandas/tests/series/test_missing.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,36 @@ def test_interpolate_akima(self):
533533
interp_s = ser.reindex(new_index).interpolate(method='akima')
534534
assert_series_equal(interp_s[1:3], expected)
535535

536+
def test_interpolate_piecewise_polynomial(self):
537+
tm._skip_if_no_scipy()
538+
539+
ser = Series([10, 11, 12, 13])
540+
541+
expected = Series([11.00, 11.25, 11.50, 11.75,
542+
12.00, 12.25, 12.50, 12.75, 13.00],
543+
index=Index([1.0, 1.25, 1.5, 1.75,
544+
2.0, 2.25, 2.5, 2.75, 3.0]))
545+
# interpolate at new_index
546+
new_index = ser.index.union(Index([1.25, 1.5, 1.75, 2.25, 2.5, 2.75]))
547+
interp_s = ser.reindex(new_index).interpolate(
548+
method='piecewise_polynomial')
549+
assert_series_equal(interp_s[1:3], expected)
550+
551+
def test_interpolate_from_derivatives(self):
552+
tm._skip_if_no_scipy()
553+
554+
ser = Series([10, 11, 12, 13])
555+
556+
expected = Series([11.00, 11.25, 11.50, 11.75,
557+
12.00, 12.25, 12.50, 12.75, 13.00],
558+
index=Index([1.0, 1.25, 1.5, 1.75,
559+
2.0, 2.25, 2.5, 2.75, 3.0]))
560+
# interpolate at new_index
561+
new_index = ser.index.union(Index([1.25, 1.5, 1.75, 2.25, 2.5, 2.75]))
562+
interp_s = ser.reindex(new_index).interpolate(
563+
method='from_derivatives')
564+
assert_series_equal(interp_s[1:3], expected)
565+
536566
def test_interpolate_corners(self):
537567
s = Series([np.nan, np.nan])
538568
assert_series_equal(s.interpolate(), s)

0 commit comments

Comments
 (0)