Pregunta

Estoy buscando encontrar el equivalente en Python de la siguiente declaración de Matlab:

vq interp1(x,y, xq,'nearest','extrap')

Parece como si interp(xq, x, y) Funciona perfectamente para interpolación/extrapolación lineal.

yo también miré

F = scipy.interpolate.interp1d(x, y, kind='nearest')

que funciona perfectamente para el método más cercano, pero no realizará la extrapolación.

¿Hay algo más que haya pasado por alto?Gracias.

¿Fue útil?

Solución

Para la interpolación lineal que se extrapolará utilizando la interpolación más cercana, utilice numpy.interp.Lo hace de forma predeterminada.

Por ejemplo:

yi = np.interp(xi, x, y)

De lo contrario, si solo desea la interpolación más cercana en todas partes, como usted describe, puede hacerlo de forma breve, pero ineficiente:(puedes hacer de esto una sola línea, si quieres)

def nearest_interp(xi, x, y):
    idx = np.abs(x - xi[:,None])
    return y[idx.argmin(axis=1)]

O de una manera más eficiente usando 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)]

Para ilustrar la diferencia entre numpy.interp y los ejemplos de interpolación más cercanos anteriores:

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()

enter image description here

Otros consejos

En versiones posteriores de SciPy (al menos v0.19.1+), scipy.interpolate.interp1d tiene la opción fill_value = “extrapolate”.

Por ejemplo:

import pandas as pd
>>> s = pd.Series([1, 2, 3])
Out[1]: 
0    1
1    2
2    3
dtype: int64

>>> t = pd.concat([s, pd.Series(index=s.index + 0.1)]).sort_index()
Out[2]: 
0.0    1.0
0.1    NaN
1.0    2.0
1.1    NaN
2.0    3.0
2.1    NaN
dtype: float64

>>> t.interpolate(method='nearest')
Out[3]: 
0.0    1.0
0.1    1.0
1.0    2.0
1.1    2.0
2.0    3.0
2.1    NaN
dtype: float64

>>> t.interpolate(method='nearest', fill_value='extrapolate')
Out[4]: 
0.0    1.0
0.1    1.0
1.0    2.0
1.1    2.0
2.0    3.0
2.1    3.0
dtype: float64

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top