zeycus
zeycus

Reputation: 890

interp2d not handling proprely unordered inputs when used

Today Python bit me, with a behavior of interp2d I did not expect. I am used to interp1d, for instance, defining

f = interp1d(np.linspace(0, 1, 10), np.linspace(1, 2, 10), kind='linear')

we get an interpolator that is sensitive to the order of the arguments its called with. f([0, 0.5, 1]) returns array([1, 1.5, 2]) while f([0.5, 1, 0]) returns array([1.5, 2], 1). As I would expect.

However, with interp2d I'm getting something different. After defining

g = interp2d([0,1], [0,1], [[1,2], [2,3]], kind='linear')

the call g([0, 0.2, 1], [0.3]) returns array([1.3, 1.5, 2.3]), but reordering the argument takes no effect. For instance, g([0.2, 1, 0]) gives me exactly the same. Which is undesired. I find no traces of this in interp2d's documentation, let alone an option to change this behavior.

I also tried and converted this example to RectBivariateSpline, the invocation raises an exception when the vector given is not ordered: ValueError("Error code returnod by bispev: 10").

I could implement a wrapper around interp2d with argsort, so that it takes care of the order and corrects it afterwards. But I find hard to believe this is the way to go, would assume it is possible to get what I want as a given. Suggestions, please!?

Upvotes: 2

Views: 523

Answers (1)

xdze2
xdze2

Reputation: 4151

There is an option assume_sorted=False in the interp2d's call function. The corresponding code is:

if not assume_sorted:
    x = np.sort(x)
    y = np.sort(y)

So by default x and y and sorted before use. However, unlike interp1d, "x and y have to be arrays of monotonically increasing values.", thus setting assume_sorted=True leads to ValueError: Invalid input data. There is no choice but to perform the interpolation using ordered x and y.

RectBivariateSpline provides the choice "Whether to evaluate the results on a grid spanned by the input arrays, or at points specified by the input arrays."

For instance:

from scipy.interpolate import RectBivariateSpline

g = RectBivariateSpline([0, 1, 2], [0, 1],
                        np.array([[0, 1, 2], [0, 1, 2]]).T,
                        kx=1, ky=1)  # x, and y are reversed compared to interp2d

x = [0.3, 0.2, 0.1]
y = [0.2, ]
print(g(x, y)) # -> ValueError: Error code returned by bispev: 10

x = [0.3, 0.2, 0.1]
y = [0.2,]*len(x)
print(g(x, y, grid=False)) # -> [0.3 0.2 0.1]

Here the output is no more values on a 2D grid (2d array) but a list of values (1d array).

Upvotes: 3

Related Questions