I'm looking to find the Python equivalent of the following Matlab statement:
vq interp1(x,y, xq,'nearest','extrap')
It looks as if interp(xq, x, y) works perfectly for linear interpolation/extrapolation.
I also looked at
F = scipy.interpolate.interp1d(x, y, kind='nearest')
which works perfectly for the nearest method, but will not perform extrapolation.
Is there anything else I've overlooked? Thanks.
For linear interpolation that will extrapolate using nearest interpolation, use numpy.interp. It does this by default.
For example:
yi = np.interp(xi, x, y)
Otherwise, if you just want nearest interpolation everywhere, as you describe, you can do it in the short, but inefficient way: (you can make this a one-liner, if you want)
def nearest_interp(xi, x, y):
    idx = np.abs(x - xi[:,None])
    return y[idx.argmin(axis=1)]
Or in a more efficient way using searchsorted:
def fast_nearest_interp(xi, x, y):
    """Assumes that x is monotonically increasing!!."""
    # Shift x points to centers
    spacing = np.diff(x) / 2
    x = x + np.hstack([spacing, spacing[-1]])
    # Append the last point in y twice for ease of use
    y = np.hstack([y, y[-1]])
    return y[np.searchsorted(x, xi)]
To illustrate the difference between numpy.interp and the nearest interpolation examples above:
import numpy as np
import matplotlib.pyplot as plt
def main():
    x = np.array([0.1, 0.3, 1.9])
    y = np.array([4, -9, 1])
    xi = np.linspace(-1, 3, 200)
    fig, axes = plt.subplots(nrows=2, sharex=True, sharey=True)
    for ax in axes:
        ax.margins(0.05)
        ax.plot(x, y, 'ro')
    axes[0].plot(xi, np.interp(xi, x, y), color='blue')
    axes[1].plot(xi, nearest_interp(xi, x, y), color='green')
    kwargs = dict(x=0.95, y=0.9, ha='right', va='top')
    axes[0].set_title("Numpy's $interp$ function", **kwargs)
    axes[1].set_title('Nearest Interpolation', **kwargs)
    plt.show()
def nearest_interp(xi, x, y):
    idx = np.abs(x - xi[:,None])
    return y[idx.argmin(axis=1)]
main()

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With