ある点列があってその間の値をどうにかして求めるいわゆる内挿を行いたい。できれば外挿まで簡単にできると嬉しい。
線形補間やスプライン補間ぐらいだったらscipy
初めいろんなライブラリに実装されているけど、
他の補間方法を使いたい時もある。そんな時に以下のコードが役に立つかもしれない。
import QuantLib as ql import numpy as np import matplotlib.pyplot as plt def interpolate(x, y, target, type): funct = type(x, y) return map(lambda target_: funct(target_, True), target) if __name__ == '__main__': dict = {"BackwardFlatInterpolation" : ql.BackwardFlatInterpolation, "ForwardFlatInterpolation" : ql.ForwardFlatInterpolation, "LinearInterpolation" : ql.LinearInterpolation, "LogLinearInterpolation" : ql.LogLinearInterpolation, "CubicNaturalSpline" : ql.CubicNaturalSpline, "LogCubicNaturalSpline" : ql.LogCubicNaturalSpline, "MonotonicCubicNaturalSpline" : ql.MonotonicCubicNaturalSpline, "MonotonicLogCubicNaturalSpline" : ql.MonotonicLogCubicNaturalSpline, "KrugerCubic" : ql.KrugerCubic, "KrugerLogCubic" : ql.KrugerLogCubic, "Parabolic" : ql.Parabolic, "LogParabolic" : ql.LogParabolic, "MonotonicParabolic" : ql.MonotonicParabolic, "MonotonicLogParabolic" : ql.MonotonicLogParabolic, "FritschButlandCubic" : ql.FritschButlandCubic, "FritschButlandLogCubic" : ql.FritschButlandLogCubic} x = np.linspace(1, 10, 10).tolist() y = (np.sin(x) + 10).tolist() target = np.linspace(1, 11, 200).tolist() plt.plot(x, y, "ro", markersize=8) for key in dict.keys(): plt.plot(target, interpolate(x, y, target, dict[key])) label = dict.keys(); label.insert(0, "raw data") plt.legend(label, "lower left")
いちいちtolist()
してるのは、そうしないと受け付けてくれないから。あと外挿フラグをTrueにしとくと外挿もいける。
直近の値の横置きで補間するBackwardFlatInterpolation
とかはよく使うと思われる。
BicubicSpline
とかBilinearInterpolation
を使えば2次元の補間もできるし、
ボラティリティ・サーフェスに特化した補間もあるのでその辺はC++のソース読むと良い。
Rで同じようなことするには以下のようなコードを書くもんだと思ってるんだけど、補間手法別に
異なる型を指定しないといけなくてうまい書き方が思いついていない・・・。
#include <Rcpp.h> #include <ql/math/all.hpp> using namespace Rcpp; using namespace QuantLib; // [[Rcpp::depends(RQuantLib)]] // [[Rcpp::plugins(openmp, cpp11)]] template <typename T> NumericVector interpolate(const NumericVector &x, const NumericVector &y, const NumericVector &target) { std::shared_ptr<T> funct(new T(x.begin(), x.end(), y.begin())); NumericVector vec(target.size()); std::transform(target.begin(), target.end(), vec.begin(), [funct](double x) -> double {return funct->operator()(x, true);}); return vec; } // [[Rcpp::export]] NumericVector f(const NumericVector x, const NumericVector y, const NumericVector target) { return interpolate<CubicNaturalSpline>(x, y, target); }