8

I want to interpolate between values in each row of a matrix (x-values) given a fixed vector of y-values. I am using python and essentially I need something like scipy.interpolate.interp1d but with x values being a matrix input. I implemented this by looping, but I want to make the operation as fast as possible.

Edit

Below is an example of a code of what I am doing right now, note that my matrix has more rows on order of millions:

import numpy as np
x = np.linspace(0,1,100).reshape(10,10)
results = np.zeros(10)
for i in range(10):
  results[i] = np.interp(0.1,x[i],range(10))
matt
  • 89
  • 3
  • 5
    A [mcve](http://stackoverflow.com/help/mcve), based on your existing code, would be helpful. – farenorth Jun 18 '15 at 01:57
  • Perhaps [this answer](http://stackoverflow.com/a/30057858/832621) covers this question... – Saullo G. P. Castro Jun 18 '15 at 05:53
  • It depends on the number of rows in your matrix. If it is small enough (say `~1000`), you shouldn't get that much overhead by using a simple loop as you have done. – rth Jun 18 '15 at 09:27
  • One could use SmoothBivariateSpline on the whole matrix. – Jon Custer Jun 18 '15 at 13:48
  • 1
    Will [`scipy.interpolate.interp2d`](http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.interp2d.html) do? And why can't you use the function returned by `interp1d` with an array argument? – Ahmed Fasih Jun 18 '15 at 13:58
  • 1
    The problem with `interp1d` is that the x-values can only be a 1D array. – matt Jun 18 '15 at 20:25
  • At first glance, it looks like you're looking for `scipy.ndimage.map_coordinates`. – Joe Kington Jun 18 '15 at 20:32
  • I am not really sure how I would use `scipy.ndimage.map_coordinates` and `scipy.interpolate.interp2d` can be applied, but it is as slow as the loop because it is interpolating in two dimensions but I only need it to interpolate in one dimension. – matt Jun 18 '15 at 22:04

1 Answers1

1

As @Joe Kington suggested you can use map_coordinates:

import scipy.ndimage as nd

# your data - make sure is float/double
X = np.arange(100).reshape(10,10).astype(float)

# the points where you want to interpolate each row 
y = np.random.rand(10) * (X.shape[1]-1)
# the rows at which you want the data interpolated -- all rows
r = np.arange(X.shape[0])

result = nd.map_coordinates(X, [r, y], order=1, mode='nearest')

The above, for the following y:

array([ 8.00091648,  0.46124587,  7.03994936,  1.26307275, 1.51068952,
        5.2981205 ,  7.43509764,  7.15198457,  5.43442468,  0.79034372])

Note, each value indicates the position in which the value is going to be interpolated for each row.

Gives the following result:

array([  8.00091648,  10.46124587,  27.03994936,  31.26307275,
        41.51068952,  55.2981205 ,  67.43509764,  77.15198457,
        85.43442468,  90.79034372])

which makes sense considering the nature of the aranged data, and the columns (y) at which it is interpolated.

Imanol Luengo
  • 15,366
  • 2
  • 49
  • 67
  • This isn't equivalent of using `np.interp` in a loop. The `y` array represents the _indices_ where each row in `X` is interpolated. What I want is essentially the interpolated index of each row in `X` given a value that lies within the particular row of `X` – matt Jun 25 '15 at 00:06
  • @matt I still see it doing what you showed in the example. If you pass `y` in my example as a vector of 0.1 values (length = num rows) you will get in return the 0.1 position interpolated in your row. Is nit that what you wanted? If not I got the question wong. – Imanol Luengo Jun 26 '15 at 23:11