Estrapolazione con metodo 'più vicino' in Python
-
20-12-2019 - |
Domanda
Sto cercando di trovare l'equivalente Python della seguente dichiarazione MATLAB:
vq interp1(x,y, xq,'nearest','extrap')
.
Sembra che interp(xq, x, y)
funzioni perfettamente per interpolazione lineare / estrapolazione.
Ho anche guardato
F = scipy.interpolate.interp1d(x, y, kind='nearest')
.
che funziona perfettamente per il metodo più vicino, ma non eseguirà l'estrapolazione.
C'è qualcos'altro che ho trascurato?Grazie.
Soluzione
Per l'interpolazione lineare che estrapolarà utilizzando l'interpolazione più vicina, utilizzare numpy.interp
.Lo fa per impostazione predefinita.
Ad esempio:
yi = np.interp(xi, x, y)
.
Altrimenti, se vuoi solo l'interpolazione più vicina ovunque, come descrivi, puoi farlo nel modo breve, ma inefficiente: (puoi renderlo un unico rivestimento, se vuoi)
def nearest_interp(xi, x, y):
idx = np.abs(x - xi[:,None])
return y[idx.argmin(axis=1)]
.
o in modo più efficiente utilizzando 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)]
.
Per illustrare la differenza tra numpy.interp
e gli esempi di interpolazione più vicini sopra:
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()
.
Altri suggerimenti
In versioni successive di Scipy (almeno v0.19.1 +), scipy.interpolate.interp1d
ha l'opzione fill_value = “extrapolate”
.
Ad esempio:
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
.