実行環境
python 3.12.11
scipy 1.16.0
numpy 2.3.1
はじめに
2021/12/25 に、補間 scipy.interpolate.interp1d おさらい という記事を書いています。
その記事で取り上げている scipy
の interp1d
クラスがレガシー扱いとなっていましたので、今回はそのことについて書きたいと思います。
なお、リファレンスに interp1d
クラスがレガシーと記載されたのは 2023/06/26 リリースの バージョン 1.11.0 からのようなので、この記事は今さらの話にはなります、ご了承ください。
リファレンスでの説明
記事投稿時点の scipy
バージョンは 1.16.0 です。
interp1d
のリファレンスはこちらになります。
レガシーについての説明は、以下の通り書かれています。
This class is considered legacy and will no longer receive updates. While we currently have no plans to remove it, we recommend that new code uses more modern alternatives instead. For a guide to the intended replacements for interp1d see 1-D interpolation.
要約です。
-
今後アップデートはしない
-
今のところ廃止の予定はない
-
これから書くコードでは別の方法を使ったほうがよい
deprecated(非推奨)とは書いてないし、廃止の予定もないとのことなので、今使っているものについては、そのまま使い続けることはできそうです。
レガシーとした理由については、ここには書かれていません。
interp1d の代わりとして推奨される方法
interp1d
の代わりとして推奨される方法(代替案)については、こちらに記載があります。
interp1d
をインスタンス化するときに kind
引数で補間の種類を指定しますが、その種類別に代替案が載っています。
以降、簡単なコードとグラフを示しながら、それぞれ確認していきます。
先に必要なライブラリをインポートし、既知点 xy、補間する x、グラフを描く関数をそれぞれ定義しておきます。
from scipy.interpolate import interp1d, make_interp_spline
import numpy as np
import matplotlib.pyplot as plt
# 既知点 xy
x = np.linspace(1, 10, num=10, endpoint=True)
y = np.cos(-x**2/9)
# 補間する x
x_new = np.linspace(0, 11, num=45, endpoint=True)
# グラフを描く関数
def graph(
kind: str,
y_alternative: np.ndarray,
label_alternative: str
):
"""
interp1d と代替案について、
それぞれの補間の結果を重ね合わせたグラフを出力
"""
f_interp1d = interp1d(x, y, kind, fill_value='extrapolate')
y_interp1d = f_interp1d(x_new)
plt.plot(x_new, y_interp1d, '-', color='silver', linewidth=4)
plt.plot(x_new, y_alternative, '--', color='red')
plt.plot(x, y, 'o')
plt.legend([f"interp1d ({kind=})", label_alternative, 'data'])
plt.show()
外挿区間にも補間する x を設けたうえで interp1d
で fill_valle='extrapolate'
として、外挿を許可しています。
既知点 xy と補間する x の位置関係はこちらのとおりです。
plt.plot(x, y, 'o')
plt.vlines(x_new, -1, 1, linewidth=0.5)
plt.legend(['xy', 'x_new'])
plt.show()
1. 線形補間
Linear interpolation,
kind="linear"
The default recommendation is to use numpy.interp function. Alternatively, you can use linear splines,make_interp_spline(x, y, k=1)
, see this section for a discussion.
kind="linear"
としていた線形補間の場合、代替案として numpy.interp の利用が推奨されています。
もしくは make_interp_spline(x, y, k=1)
を使うこともできるようです。
まず、numpy.interp
を確認します。
kind = 'linear'
y_alternative = np.interp(x_new, x, y)
graph(kind, y_alternative, 'np.interp')
灰色の実線が interp1d
による補間の結果、赤色の破線が代替案の結果です。
内挿区間(x が 1 ~ 10 の区間)では同じ結果となりますが、外挿区間では結果が異なります。
外挿をするときは注意が必要です。
つづいて、make_interp_spline
の結果です。
kind = 'linear'
f_alternative = make_interp_spline(x, y, k=1)
y_alternative = f_alternative(x_new)
graph(kind, y_alternative, 'make_interp_spline(k=1)')
make_interp_spline
では、外挿区間も補間していることがわかります。
2. スプライン補間
Spline interpolators,
kind="quadratic" or "cubic"
Under the hood, interp1d delegates to make_interp_spline, so we recommend using the latter directly.
kind="quadratic"
または kind="cubic"
としてた場合の代替案としても、 make_interp_spline
の利用が推奨されています。
"linear"
では k=1
としていましたが、"quadratic"
では k=2
、"cubic"
では k=3
とします。
デフォルトは k=3
です。
kind = 'quadratic'
f_alternative = make_interp_spline(x, y, k=2)
y_alternative = f_alternative(x_new)
graph(kind, y_alternative, 'make_interp_spline(k=2)')
kind = 'cubic'
f_alternative = make_interp_spline(x, y, k=3)
y_alternative = f_alternative(x_new)
graph(kind, y_alternative, 'make_interp_spline(k=3)')
どちらも interp1d
と同じ結果になっています。
3. 前後の値をあてはめる補間
Piecewise constant modes,
kind="nearest", "previous", "next"
First, we note thatinterp1d(x, y, kind='previous')
is equivalent tomake_interp_spline(x, y, k=0)
.
More generally however, all these piecewise constant interpolation modes are based on numpy.searchsorted.
つぎに、kind="nearest", "previous", "next"
としていた場合の代替案です。
"previous"
については make_interp_spline(x, y, k=0)
と同じ処理になるそうです。
kind = 'previous'
f_alternative = make_interp_spline(x, y, k=0)
y_alternative = f_alternative(x_new)
graph(kind, y_alternative, 'make_interp_spline(k=0)')
interp1d
では左側の外挿区間では補間していませんが、make_interp_spline
では直後の値を使って補間しています。
直前の値がないにもかかわらず値をあてはめる結果となるので、"previous"
の代替で make_interp_spline
を使う場合は注意が必要です。
さて、上述のとおり "previous"
については make_interp_spline
を使った方法が紹介されていますが、"nearest"
と "next"
については make_interp_spline
で代替できるとは書かれていません。
make_interp_spline
を使った "previous"
の補間が「推奨」ではなく「同等」とされていることも併せて考えると、"nearest"
, "previous"
, "next"
については interp1d
を使い続けるという選択肢で構わないのではないかと思います。1
4. その他
リファレンスには取り上げられていませんが、kind="nearest-up", "zero", "slinear"
の場合についても説明します。
"nearest-up"
と "nearest"
の違いは、中間の補間に直後の値を使うか、直前の値を使うかの違いです。
したがって "nearest"
と同様、"nearest-up"
も interp1d
を継続して使うということで良いように思います。
"zero"
と "spline"
は、それぞれ make_interp_spline
で k=0
,k=1
とした補間に相当するようです。
kind = 'zero'
f_alternative = make_interp_spline(x, y, k=0)
y_alternative = f_alternative(x_new)
graph(kind, y_alternative, 'make_interp_spline(k=0)')
kind = 'slinear'
f_alternative = make_interp_spline(x, y, k=1)
y_alternative = f_alternative(x_new)
graph(kind, y_alternative, 'make_interp_spline(k=1)')
"zero"
, "slinear"
の代替案は公式に紹介されているものではないので、参考に留めてください。
おわりに
scipy.interpolate.interp1d
クラスがレガシーとなっています。
これまでのコードを書き換える必要はないということですが、新しくコードを書く場合は別の方法が推奨されています。
今回補間の種類別にグラフを描いて、外挿区間の補間の扱いが interp1d
とその代替案で違う場合があることを確認しました。
既知の範囲内での内挿補間が望ましいですが、やむを得ず外挿をすることもあります。
外挿をする場合は、Extrapolation tips and tricks の注意点もご確認ください。
-
interp1d
の使用を避ける場合は、interp1d
の内部でも使用されている numpy.searchsorted を使って独自に実装することが考えられます。詳しくはinterp1d
の ソースコード にて、ご確認ください ↩