基本的なモジュールの説明

Pythonのモジュール・パッケージ

これまでに、

  • 自分がよく使う数は『変数』に置き換えておいたほうが便利。

  • 自分がよく 使う計算・命令は『関数』としてまとめておいたほうが便利。

ということを学びました。

変数や関数は自分が作るだけではありません。python には(他の多くのプログラミング言語と同じように)「世界の人がよく使う数や計算・命令をまとめたもの。関数や変数のまとまり。」が、たくさん用意されています。その一つ一つは module と呼 ばれ、複数の module を用途ごとにまとめたものが package と呼ばれます(さらに複数のpackageをまとめたものをlibraryと呼びますが、実際にはpackageとlibraryの違いは特に意識されることは少ないようです)。

通常、moduleやpackage を利用するには、自分で一つずつインストールする必要があるのですが、 前述のようにAnacondaをインストールした時点で、科学技術計算で頻繁に使う パッケージ がすでにインストール済みで、すぐ使えるようになっています。以下では物理の実験データを解析する上でよく使うパッケージについて説明します。

SciPy

SciPy(サイパイと発音)とは、科学技術分野でよく使う計算や命令・解析ツールなど をひとまとめにした package です。例えば物理定数や数学定数をまとめた moduleの、 scipy.constants を使ってみましょう。新しいコードセルに

from scipy import constants
constants.c

と入力し、実行してみてください。すると、真空中の光速の SI 単位系での値が出てきたと思います。1行目は、scipy というパッケージから、constants という module を読み込む(=このノートブックで使えるようにする準備をする)という命令に対応しています。このimport作業は、基本的には同じnotebookの中で1度だけ実行すれば十分です。2行目は、constantsモジュールの中にある変数cの中身を取ってくるという命令です。光速以外にもたくさんの定数が利用可能で、もちろん 計算に使うこともできます。他の定数の詳細はhttps://docs.scipy.org/doc/scipy/ reference/constants.html#module-scipy.constantsを参照してください。

SciPy では、他にも微分積分やフーリエ変換、フィッティングなど、便利な機能がたくさ ん揃っています。例えば定積分は

from scipy import integrate
def x_cubic(x):
    return x**3
integrate.quad(x_cubic, 0, 1)

のように計算できます。1行目はscipyからintegrateというモジュールを読み込むという命令です。その次の行では、定積分がうまくいくか試すために、x_cubicという関数を自分で作って定義しています。これは、代入された数値の3乗を返すだけの関数ですね。最後の行で、実際に定積分を実行しています。integrateモジュールの中のquadという関数を呼び出しています。quad関数は、定積分を行ってくれる関数です。このセルを実行すると

01dxx3\int_0^1dx x^3

の計算結果として「(0.25, 2.7755575615628914e-15)」と返ってくると思います。quadには、まず被積分関数の名前を渡し、次に定積分の下限と上限を渡します。結果として、返ってくるのは、最初の数字が定積分の結果そのもの、2 つ目の数字が推定される計算誤差を表しています。この例のように、関数からは複数の値がセットになって返ってくることもあります。

NumPy

実際の実験データというのは、たくさんの数値の列であることが多いと思います。例えば、時間とともに何かが変化する様子を測定したり、場所依存するデータを測定したり、信号の周波数成分を測定したり、といった場合があるでしょう。すると測定の結果として、長い数値の列が手に入ることになります。このような長い数値列を効率的に簡便に扱うためのパッケージとして numpy(ナムパイ、ナンパイと発音)が提供されています。実際に numpy を使って みましょう。新しいコードセルに

import numpy as np
x = np.array( [1, 2, 3, 4, 5, 6])
x**2

と打ち込んで、実行してみてください。1〜6 までの数字の 2 乗の数列が結果として出力されたと思います。1行目は numpy パッケージを np という名前に変えてから読み込むという命令に対応しています。np.array は 「numpyのarray という形式」で数列を作る関数を呼び出していることを意味しています。このようにして用意したarray形式の数列は、まとめて効率的に操作可能なのが大きな特徴です。3行目では一見、xという数値の2乗を計算しているように見えますが、実際にはxの中身はarray形式の数列です。このようにarrayに計算を行うと、「良い感じに」数列の要素ごとに計算をまとめて行ってくれます。今回の場合、一度に各数字の2乗を計算しているということになります。

(上のコードのnp.array()の中にある[1,2,3,4,5,6]というのはというのは、numpyではなく、大元のpython に元から備わっている「リスト」というもので、数字や文字の列を作ることができます。つまり np.array() は、python のリストを numpy array に変換しているということになります。そうすると、「そもそも numpy array を使わずに、python のリストを使えば十分ではないか?」と、思う人がいるかもしれません。しかし両者には大きな違いがいくつもあります。例えば、本文中で説明しているように numpy array のいいところは、 数列をまとめて操作可能なところです。

y = [1, 2, 3, 4, 5, 6]
y**2

のように、実行してみようとしても、エラーが出て実行できないはずです。リストの場合、要素ごとにしか操作できないため、リストの要素すべてに同じ計算をしようと思うと、コードが煩雑になりますが、数値リストを numpy array の形式に変更す ることで array を全体に命令することができるようになります。)

この例のように python では変数の中に、実数や整数だけではなく、numpy array のようなものも代入することができます。便利でもあり複雑でもある概念なので、しっかりと使えるようにしましょう。

他の例を見てみましょう。例えば、実験データの解析では、真値とのずれ、つまり誤差の評価が必要になる場合があります。ここでは誤差の指標として、2乗平均平方根を利用しましょう。2乗平均平方根は

i=1N(xix0)2N\sqrt{\dfrac{\sum_{i=1}^N \left(x_i-x_0\right)^2}{N}}

で計算できます。ここで xi は N 個の測定値、x0 は対応する真値を表しています。実際に

測定値:2.1, 2.9, 1.9, 3.0, 2.05, 3.1

真値:2, 3, 2, 3, 2, 3

という場合に、誤差を評価するプログラムを書いてみましょう。

module は、同じノートブック上であれば、一度読み込めば再度読み込む必要はありません。上で、すでにnumpy は読み込んでいるはずなので、ここでは読み込み直す必要はありませ ん。新しいセルに

x = np.array( [2.1, 2.9, 1.9, 3.0, 2.05, 3.1]) 
x0 = np.array([2, 3, 2, 3, 2, 3])
np.sqrt(np.mean((x-x0)**2))

と入力、実行してみてください。2 乗平均誤差が出力されます。np.sqrtは平方根を計算する関数で、np.meanは渡されたnumpy arrayの平均値を計算する関数です。

numpy arrayを扱う上でよく使うのがスライスという機能です。これはarrayの一部だけを取り出す機能です。たとえばxの最初から3つだけを取り出したい場合

x[0:3]

とします。例えば3番目までの2乗平均誤差は

x = np.array( [2.1, 2.9, 1.9, 3.0, 2.05, 3.1]) 
x0 = np.array([2, 3, 2, 3, 2, 3])
np.sqrt(np.mean((x[0:3]-x0[0:3])**2))

で計算できます。

2番目から5番目を取り出したい場合は

x[1:5]

のようにします。つまり、一般にはa番目からb番目だけを取り出したい場合に

x[a-1:b]

とします。また、1番目の数値を省略した場合は最初から、2番目の数値を省略した場合は

x[1:]

の中身は、xの2番目から最後までを取り出したものになります。いちいちスライスを繰り返すが面倒な場合は、新しい変数を作ってしまいましょう。

x_part=x[:3]

ある範囲ではなく、1つだけを取り出したい場合には

x[2]

のようにします。このとき取り出されるのは2番目ではなく3番目であることに注意しましょう。pythonの世界では、何かを数えるときは基本的に0から数え始めるためです。実は負の数も使うことができます。これは後ろから何番目かを指定するもので

x[-1]

とすると、最後の数値をとってくることができます。x[-2]なら最後から2番目ですね。

Matplotlib

実験データを解析しても、数値だけでは理解がなかなか難しい場合があります。そこで、可視化・グラフ化する必要がでてきます。pythonではグラフを作るためのpackageがたくさんあります。ここではMatplotlib(マットプロットリブ、マトプロトリブと発音。MATLABを参考に作られています)を紹介します。

早速グラフを作ってみたいのですが、そのためにはプロットする対象である元データが必要です。ここでは、上ですでに作っているnumpy arrayのxを利用しましょう。

import matplotlib.pyplot as plt
fig1, ax1 = plt.subplots()
curve1 = ax1.plot(x, marker='o',c='b')

を実行すると図のようなグラフが作られるはずです。

大まかな流れを説明していきましょう。まず、最初の行で、プロットに使うためのpyplotというモジュールをpltという名前に変えて読み込みます。

次の行ではplt.subplots()という関数を呼び出して、グラフを書くための準備をします。この関数を呼び出すことで、FigureというオブジェクトとAxesというオブジェクトの2個が返ってきます。そこで、各々を変数fig1と変数ax1に代入しています。と言っても、オブジェクトというのが何なのかわからないかもしれません。ここで『fig1とax1という変数には、「抽象的な意味で」グラフの描画領域が代入されている』と理解してください。ここで「抽象的な意味で」というのは「fig1やax1の中身がどんな数字なのか、といったことを気にする必要はない。fig1もax1も、グラフに描きたいものを追加したり、設定変更したりする際に使う、単なる道具」くらいに思っておいてください。それでは、fig1とax1の違いは何なのかというと、グラフ中のどの領域を変更したいかで、使い分けます。グラフを描画する領域がfigure領域とaxes領域に分かれており、それぞれに対応しています。どのように分かれているかは、https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/Python4_DataAnalysis.htmlの3.2の図を参考にしてください。この図からわかるように、axes領域が一つしかない場合には、figure領域とaxes領域の違いがわかりにくくなっています。実際、axes領域をいじることはあっても、figure領域をいじることは、ほとんどありません。

  • 複数のグラフを縦横に並べるとき

  • 今見えているグラフの外側に何かを置きたいとき

に、figure領域を意識する必要があると覚えておきましょう。それ以外は、axes領域だけ(つまり今回の例ではax1という変数だけ)を気にすれば良いでしょう。

最後の行では、ax1.plot()関数を呼び出し、numpy array xのデータをグラフ化しています。curve1には「抽象的な意味で」グラフの直線(曲線)が代入されています。marker='o'は、塗りつぶした丸印のマーカーでデータ点を表すという意味で、c='b'は色(Color)として青色(Blue)を使うという意味です。マーカーの種類は、他にもたくさんあります(マニュアルの該当ページを参照)。色は'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'のように文字で指定するか、あるいは赤緑青(RGB)の数値で (0.1, 0.2, 0.5) のように指定することができます。

先程描いた図では、横軸のデータを何も指定していないので、1つ目のデータは横軸0の位置に、2つ目のデータは横軸1の位置に、3つ目のデータは横軸2の位置に、4つ目のデータは横軸3の位置に、、、、とプロットされています(1からではなく0から始まるのは、pythonを含む多くのプログラミング言語の特徴です)。実際の実験データを可視化する際には、もちろん横軸に対応するデータがあるはずです。

例えば、先程のデータxは、0.1秒ごとに、振り子の座標を記録したものだとしましょう。対応する横軸データを作るには

t =  np.arange(x.size) * 0.1

を実行しましょう。x.sizeはnumpy array xの要素の数(今回の場合6)を意味しています。そして、np.arange()は、numpy arrayの形式で等差数列をつくる関数です。デフォルトでは最初の数値が0で公差が1の数列を作るように働きます。その関数に6を代入しているので、「6の手前までの等差数列」を作ることになります。今回の場合、0,1,2,3,4,5が作られます。これに0.1がかけられるので、結果的に変数tには(0,0.1,0.2,0.3,0.4,0.5)というnumpy arrayが変数tに代入されます。(一般には、np.arange()は、3つの数字を代入することもできます。np.arange(start, stop, step)と実行すると最初の数字がstartで公差がstepで、stopの手前で終わる等差数列が作られます)。このnumpy array tを横軸データとして、グラフを作り直しましょう。そのために、

import matplotlib.pyplot as plt
fig1, ax1 = plt.subplots()

curve1 = ax1.plot(t,x, marker='o',c='b')

と実行してみましょう。次のような図が得られます。

せっかく横軸をきちんとしたものに変えたので、横軸と縦軸がどういう量なのかも書きましょう。

fig1, ax1 = plt.subplots()

curve1 = ax1.plot(t,x, marker='o',c='b')
ax1.set_xlabel("time (s)")
ax1.set_ylabel("position (m)")

を実行すると、たしかに軸ラベルを追加することができます。

また、複数のデータを同じグラフ上にプロットしたい場合には

fig1, ax1 = plt.subplots()

curve1 = ax1.plot(t,x, marker='o',c='b')
curve2 = ax1.plot(t,x0, marker='v', c='r')
ax1.set_xlabel("time (s)")
ax1.set_ylabel("position (m)")

のように、curveのところを増やしていきましょう。

ここまで、実験データを可視化するための基礎を説明してきました。グラフの見栄えを整える方法や、異なるプロットの方法、実験データの基本的な解析などを説明していきます。

最終更新