scipyによる3次スプライン補完
未知の関数に出会った時3次スプライン補完をしたいと思うのは人類の普遍的欲求です。 普遍的欲求はだいたいpythonのライブラリが満たしてくれるもので、今回のケースではscipyがその役割を担ってくれます。
scipyの3次スプライン補完についてはいくつか日本語解説ページがあるのですが、
ここで使われているkind='cubic'
のinterp1d
関数だと、スプライン補完の係数取得に少々非自明な処理をする必要が出てきます。
人間が3次スプライン補完をするときって、欲しいものは大抵関数そのものではなく係数なので、これは困りますね。
さて、scipyではinterp1d
以外にもCubicSpline
関数で3次スプライン補完を実行することができ、こちらを使えばこの問題は解決します。
使い方は以下
import numpy from scipy import interpolate import matplotlib.pyplot as plt if __name__ == '__main__': x_coordinates = [] y_coordinates = [] for line in open('test.txt', 'r'): point = [float(coord.split()[0]) for coord in line.split(',')] x_coordinates.append(point[0]) y_coordinates.append(point[1]) spline_func = interpolate.CubicSpline(x_coordinates, y_coordinates) print(spline_func.c) # ここで係数を取得しています x_res = numpy.linspace(1, 5, 200) y_res = spline_func(x_res) plt.plot(x_coordinates, y_coordinates, 'o', x_res, y_res) plt.show()
CubicSpline
の返り値であるPPoly
オブジェクトのc
を呼び出すことで、係数にアクセスしています。
テストデータとしては下記を使用しました。
1.5, 1.65 1.677, 5.64 2.3, 5.53 3.0, 4.354 3.8, 3.555
出力グラフ
標準出力(コメント部分は後から追記)
[[ 25.17215028 25.17215028 -3.16687764 -3.16687764] # 3次の係数 [-52.99186318 -39.62545138 7.42129748 0.77085443] # 2次の係数 [ 31.13331437 14.74004969 -5.32313819 0.41136815] # 1次の係数 [ 1.65 5.64 5.53 4.354 ]] # 定数項
バージョン情報
$ python -V
Python 3.5.2
>>> import scipy as sp >>> sp.version.full_version '0.18.1'
参考
https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.CubicSpline.html
matplotlibでのオブジェクト指向的な描画
matplotlibには主にpyplotの関数を用いてオブジェクトを明示的に操作せず簡単に描画する方法と、オブジェクトを明示的に操作する方法がある。以下後者の方法について。
matplotlibではグラフは一度FigureCanvasに描画され、それがバックエンドのmatplotlib.backend_bases.FigureCanvasBaseを継承した出力フォーマット依存のクラスによって出力されるという仕組みをとっている(はず、要出典)。
FigureCanvasに描画されるFigureは部品ごとに管理されており、すべての部品はmatplotlib.artist.Artistという抽象基底クラスを継承している。Figure自身もArtistの派生クラス。部品というのは例えば、軸(Axisというクラスで管理される)や目盛り、グリッド線(Tickというクラスに管理される)などのことを指す。また、これらはこちらもまたArtistの派生クラスであるmatplotlin.axes.Axesによってまとめられ、管理されている。
オブジェクト指向でのプロットは以下のようになる(例として2つの行列から2つのカラーマップを描く場合を取り上げる)。
import matplotlib.pyplot as pet import matplotlib.cm as cm #データを用意する arr1 = [[1,0,0],[0,1,0],[0,0,1]] arr2 = [[0,0,1],[0,1,0],[1,0,0]] data = [arr1,arr2] #Figure全体を管理するオブジェクトfigを生成する fig = plt.figure() #Figureの構成要素である2つの図それぞれを管理するAxesオブジェクトax1とax2を生成する ax1 = fig.add_subplot(1,2,1)#1行2列のグラフの1つめを描く ax2 = fig.add_subplot(1,2,2)#1行2列のグラフの2つめを描く ax1.imshow(data[0], cmap = cm.Greys, interpolation = 'nearest')#オブジェクトにカラーマップの情報をもたせるAxesのimshowメソッドを呼び出す ax1.set_axis_off()#軸を表示しない設定にするset_axis_off()メソッドを呼び出す ax2.imshow(data[1], cmap = cm.Greys_r, interpolation = 'nearest') ax2.set_axis_off() #描画する plt.show()
上記コードのうちcm.binaryは色を指定している。指定できる色は(http://matplotlib.org/examples/color/colormaps_reference.html)にある。”Greys_r”の”_r”は、グラデーションを反転させている。ここにない色も指定できたりする(例えば”binary”)。また、interpolationの’nearest’は描画をタイル状にしており、無指定だとグラフはグラデーションになる。
図の詳細な設定をいじる場合は図を管理しているAxesオブジェクトのメソッドを使う、というような事になる。Axes.get_xaxisなどのメソッドを使ってX軸の情報のみを管理するXAxisオブジェクトを生成し、更に細かく設定を行うことも(多分)できる。このようなAxesクラスのメソッドは(http://matplotlib.org/api/axes_api.html#axis-limits)に書いてある。
matplotlib version2.0.0をインストールした作業記録[Ubuntu 16.04]
Ubuntu 16.04に何も考えずaptでmatplotlibを入れたらversionが1.5.1だった。バージョンの確認は
$ python >>> import matplotlib >>> matplotlib.__version__
でできる。
最新版は2.0.0なのでこちらに更新したい。また、今まではpythonで使っていたが折角なのでpython3で使いたい。以下作業ログ。
$ apt search python3-matplotlib
の結果aptで入れられるのは1.5.1までらしい。apt-get updateしても変わらなかった。
少し調べてみるとどうもpythonのパッケージ管理システムpipで入れることができるらしい。そういうわけで、まずはpipを入れる(aptとpipが後々衝突したりしないかとても不安だけれど取り敢えず気にせず入れてみる)。
$ apt search python3-matplotlib
の結果python3-pipがヒットしたのでインストールする。
$ sudo apt-get install python3-pip
pipが入ったので以下でmatplotlibを探そうとしたらpipがまだ入っていないと怒られた。
$ pip search matplotlib
pipという名前では入っていないようなので名前を特定する。/usr/bin内を探したところ、pipというファイルはなかったが代わりにpip3というファイルがあった。おそらくこれだと思われるのでpip3で呼べば良い。
さてmatplotlibのインストールといきたいところだが、念の為以前入れていたmatplotlibを削除しておく必要がある。
$ sudo apt-get purge python-matplotlib
で以前のmatplotlibを削除した。purgeだと設定ファイルごと削除してくれるらしい。
pip3でmatplotlibを検索する。
$ pip3 search matplotlib
matplotlib (2.0.0)がヒットしてくれたのでこれをインストールする。
$ pip3 install matplotlib
ちゃんとpython3のmatplotlib(2.0.0)が入っているかどうか確認する。
$ python3 >>> import matplotlib as mpl >>> mpl.__version__
と打ったら
'2.0.0'
と帰ってきたので無事完了したか?と思ったのだけど、その後
$ python3 (実行ファイル名).py
ImportError: No module named '_tkinter', please install the python3-tk package
と怒られてしまった。python3-tkパッケージがないということなのでpip3でsearchをかけたがそれらしきものがない。
$ apt search python3-tk
としたらヒットしたのでaptで入れることにする。
$ sudo apt-get install python3-tk
こうしたら実行ファイルもちゃんと動くようになった。めでたしめでたし。