Comment faire de scipy.interpoler donner une extrapolation de résultats au-delà de l'entrée de gamme?
Je suis en train de le port d'un programme qui utilise un roulé à la main de l'interpolateur (développé par un mathématicien collègue) sur l'utilisation de la interpolateurs fournis par scipy. Je voudrais utiliser ou enveloppez la scipy de l'interpolateur de sorte qu'il a d'aussi près que possible du comportement de l'ancien de l'interpolateur.
Une différence essentielle entre les deux fonctions est que, dans l'origine, notre interpolateur - si la valeur d'entrée est au-dessus ou au-dessous de l'entrée de gamme, origine, notre interpolateur permettra d'extrapoler le résultat. Si vous essayez cela avec le scipy interpolateur il soulève un ValueError
. Considérer ce programme comme un exemple:
import numpy as np
from scipy import interpolate
x = np.arange(0,10)
y = np.exp(-x/3.0)
f = interpolate.interp1d(x, y)
print f(9)
print f(11) # Causes ValueError, because it's greater than max(x)
Est-il un moyen judicieux de faire en sorte qu'au lieu de s'écraser, la dernière ligne sera tout simplement faire un linéaire d'extrapoler, de poursuivre les gradients défini par la première et la dernière de deux points à l'infini.
Noter, que dans le réel, le logiciel que je ne suis pas vraiment à l'aide de la fonction exp - c'est ici, à des fins d'illustration seulement!
scipy.interpolate.UnivariateSpline
semble extrapoler sans problèmes.
Vous devez vous connecter pour publier un commentaire.
1. Constante extrapolation
Vous pouvez utiliser
interp
fonction de scipy, il extrapole à gauche et à droite des valeurs comme constante au-delà de la portée:2. Linéaire (ou d'autres personnalisé) extrapolation
Vous pouvez écrire un wrapper autour d'une fonction d'interpolation qui prend soin de l'extrapolation linéaire. Par exemple:
extrap1d
prend une fonction d'interpolation et retourne une fonction qui peut aussi extrapoler. Et vous pouvez l'utiliser comme ceci:De sortie:
list
pour le retour:return array(list(map(pointwise, array(xs))))
pour résoudre l'itérateur.Vous pouvez prendre un coup d'oeil à InterpolatedUnivariateSpline
Voici un exemple de son utilisation:
I used k=1 (order)
, de sorte qu'il devient une interpolation linéaire, etI used bbox=[xmin-w, xmax+w] where w is my tolerance
Que de SciPy version 0.17.0, il y a une nouvelle option pour scipy.interpoler.interp1d qui permet l'extrapolation. Réglez simplement fill_value='extrapoler" dans l'appel. La modification de votre code de cette manière donne:
et la sortie est:
Ce sujet scipy.interpoler.splrep (avec le degré 1 et pas de lissage):
Il semble faire ce que vous voulez, depuis 34 = 25 + (25 - 16).
Voici une autre méthode qui utilise uniquement le numpy paquet. Il faut profiter de numpy du tableau de fonctions, de manière peut-être plus rapide lorsque l'interpolation/extrapolation de grands tableaux:
Edit: Marque Mikofski de la modification proposée de la "extrap" fonction:
y[x < xp[0]] = fp[0] + (x[x < xp[0]] - xp[0]) / (xp[1] - xp[0]) * (fp[1] - fp[0])
ety[x > xp[-1]] = fp[-1] + (x[x > xp[-1]] - xp[-1]) / (xp[-2] - xp[-1]) * (fp[-2] - fp[-1])
au lieu denp.where
, depuis leFalse
option,y
ne change pas.Il peut être plus rapide d'utiliser boolean indexation avec grands ensembles de données, puisque l'algorithme vérifie si chaque point est en dehors de l'intervalle, alors que booléenne indexation permet une plus facile et plus rapide comparaison.
Par exemple:
Dans mon cas, avec un ensemble de données de 300000 points, ce qui signifie une vitesse de 25,8 à de 0,094 secondes, ce qui est plus de 250 fois plus rapide.
Je l'ai fait par l'ajout d'un point pour mes premiers tableaux. De cette façon, j'ai éviter de définir des self-made fonctions, et l'extrapolation linéaire (dans l'exemple ci-dessous: droit de l'extrapolation) semble ok.
J'ai peur qu'il n'est pas facile de faire cela dans Scipy à ma connaissance. Vous pouvez, comme je suis assez sûr que vous le savez, désactiver les limites d'erreurs et de combler toutes les valeurs de la fonction au-delà de la gamme, avec une constante, mais qui n'aide pas vraiment. Voir cette question sur la liste de diffusion pour encore plus d'idées. Peut-être que vous pourriez utiliser une sorte de par morceaux de la fonction, mais qui semble comme une grande douleur.
Standard interpoler + linéaire extrapoler:
Le code ci-dessous vous donne la simple extrapolation du module. k est la valeur à laquelle l'ensemble de données y doit être extrapolées sur la base des données définir x. Le
numpy
module est nécessaire.