In [1]:
% matplotlib inline

5 モジュールのインポートと使い方

これまで,出てきた関数(print(), input(), int(), list()などなど)は組み込み関数と呼ばれるものです.組み込み関数以外の特定の用途で使用する関数やメソッドをまとめたものをモジュールと呼び,複数のモジュールをまとめたものをパッケージ呼びます.ただし,モジュールとパッケージの区別は厳密ではありません.モジュールAの中にモジュールBが含まれている場合に,モジュールAをパッケージと呼んでいるだけです.Pythonでは標準で用意されているモジュールは標準ライブラリと呼ばれ,それらのモジュールを上手く使うことで比較的容易にプログラミングを実行できます(標準ライブラリ).また,Pythonでは標準ライブラリ以外にとても便利で高度な機能を持つパッケージが数多く用意されてます.それらのパッケージの大部分はPyPI(Python Package Index 左のボックスにPython3のパッケージリストがあります,ある"Browse packages"に必要なパッケージがあります)に登録されており,自由にインストールし使うことができます.実は皆さんのPCにはPythonをインストールした段階で科学技術計算に使用する多くのパッケージがインストールされています(PyPIから自由に必要なパッケージを取ってきて使用する方法はここでは説明しません).

(一部の)標準ライブラリの紹介

モジュール名 モジュールの機能 (独断と偏見の)数理工学科学生のための重要度
re 正規表現
math 数学関数 ×(より高機能なnumpyで代用)
decimal 10進固定及び浮動小数点数の算術演算 ×(より高機能なnumpyで代用)
random 疑似乱数生成 ×(より高機能なnumpyで代用)
sys システムパラメータ
os osのインターフェース
csv csvファイルの読み書き ×(より高機能なpandasで代用)

便利で有名な拡張パッケージの紹介

パッケージ名 パッケージの機能
numpy 数値計算ライブラリ
matplotlib (主に2D)グラフ作成ライブラリ
scipy 科学技術計算ライブラリ(数値積分,線形代数演算,FFT,乱数etc)
pandas 統計解析のフォーマット(フレームワーク)ライブラリ
statsmodels 統計解析ライブラリ
sympy 数式処理ライブラリ
scikit-learn 機械学習ライブラリ
opencv 画像処理ライブラリ
openGL 2D,3Dコンピュータグラフィックス(動画など)
networkX ネットワーク解析ライブラリ
kivy マルチタッチアプリ開発ツールキットライブラリ
tensorflow (Googleが満を期して出した)機械学習・人工知能ライブラリ(2016年度半ばからPythonにしか対応)

ここでは幾つかの便利なパッケージを使いながらモジュールの使い方に慣れましょう.

5.1 モジュールの使い方1(mathモジュールを例に)

数学関数などを扱うためのPythonの標準パッケージの中にmathモジュールがあります.ここではmathモジュールを例にモジュールの使い方を学びます.(実は,より強力な数値計算のための拡張パッケージとしてnumpyパッケージがあります.皆さんが将来卒研などに取り組む際にはmathを使わずnumpyを使うことになるでしょう.numpyマニュアル

In [2]:
import math
print(math.radians(180)) # numpyパッケージのradians()関数を用いて引数"180"度をラジアン表現に変換する
3.141592653589793

上記プログラムは,下記の動作をします.

  1. 1行目でmathモジュールを読み込み
  2. 2行目でmathモジュール内で定義されているradians()関数を用いて"180度"を$\pi$ラジアンへ変換する

このように,モジュールは

import モジュール名(パッケージ名)

で導入できます. そして,導入したモジュール内で定義されている関数は

モジュール名.関数( )

という形で使用できます.

また,モジュール名を記述せず関数を直接利用したい場合は

from モジュール名 import 関数名

とします.下記のプログラムは上のものと同じ結果を示します.

In [3]:
from math import radians
print(radians(180))
3.141592653589793

また,mathモジュールに含まれるすべての関数を直接利用した場合は下記のように記述します.

In [4]:
from math import *
print(radians(180))
print(exp(0))
3.141592653589793
1.0

ただし,上述のように関数名を直接用いる時には,同じ関数名をプログラム内で使用しないように注意してください.

関数名の重複を避けかつモジュール名を短く表現したい場合はas演算子を用います.

In [5]:
import math as mt
print(mt.radians(180))
print(mt.pi)
3.141592653589793
3.141592653589793

5.2 モジュールの使い方2(matplotlibパッケージを例に)

matplotlibパッケージ(グラフ作成パッケージ)の中に含まれているpyplotモジュールを呼び出す方法は次のようにします.(matplotlibの使い方はすぐ後でやります)

In [6]:
import matplotlib.pyplot
x = list(range(0,10))
y = list(range(0,20, 2))
matplotlib.pyplot.plot(x, y)
matplotlib.pyplot.show()

上記のプログラムは下記を実行してます.

  1. 1行目でmatplotlibパッケージ内で定義されているpyplotモジュールを読み込んでます
  2. 2行目でxにリスト[0, 1, ・・・, 9]を代入
  3. 3行目でyにリスト[0, 2, ・・・, 18]を代入

このようにパッケージ内でさらにモジュールとしてまとめられている関数は

パッケージ名.モジュール名.関数( )

という形で呼び出すことができます(4,5行目は後で説明します).

モジュールと同様に"as"演算子を用いパッケージ+モジュール名を短くすることができる

In [7]:
import matplotlib.pyplot as plt # "matpotlib.pyplot"モジュールを"plt"という名前でインポート
x = list(range(0,10))
y = list(range(0,20, 2))
plt.plot(x, y) # matplotlib.pyplot.plot(x, y)を同じ意味
plt.show()

問題

標準ライブラリの一つであるrandomモジュールには$[0, 1]$区間の一様乱数を返すrandom()関数が定義されてます.

  1. randomモジュールからrandom()関数をインポートし,10個の乱数($[0, 1]$区間)を要素として持つリストを作成して下さい.
  2. 上述のプログラムを変更し,10個の乱数(1~6の整数)を要素として持つリストを作成して下さい.(これはサイコロを10回ふってその値をリストに代入することと同じです)

6 matplotlibパッケージの使い方

さて,上記のモジュールの使い方を学びましたのでここでは2次元グラフの表示できるパッケージmatplotlibの使い方を学びます. 科学技術計算においてデータ列を2次元や3次元のグラフにプロット場合や数式を2次元や3次元の空間に記述し視覚化することはとても大切です.matplotlibはPythonに導入された2次元、3次元グラフ作成の拡張パッケージです(マニュアルはここ).

6.1 基本的な使い方

順番に使い方を見てみましょう.まずは$y= \sin{x}$ $(0 \leq x \leq 2\pi)$の関数を出力します.

In [1]:
# sin関数の表示[0, 2pi) (このプログラムはスマートなプログラムではありません.分かり易さを重視してます)
import math
import matplotlib.pyplot as plt
x, y = [],[]
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))
plt.plot(x, y)
plt.show()

上記のプログラムは下記を実行してます.

  1. 1行目:mathパッケージを読み込み
  2. 2行目:matplotlibパッケージ内で定義されているpyplotモジュールを読み込んでいます
  3. 3行目:空のリストx, yを準備
  4. 4行目:0から396まで18おきに繰り返す
  5. 5行目:mathパッケージのradians()関数を用いてiをラジアンに変換し,リストxへ付け加える
  6. 6行目:ラジアンに変換したx[i]sin関数の引数としリストyへ付け加える(要するに$y_i=\sin{x_i}$)
  7. 7行目:$(x_i, y_i)$の組をグラフとして表示
  8. 8行目:グラフをディスプレイに表示

とは言え、分かり易さを優先し以下ではforループを用いて書きます。

In [11]:
# X軸、Y軸の表示
import math
import matplotlib.pyplot as plt
x, y = [],[]
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))

plt.plot(x, y)
plt.xlabel("X", fontsize=20) # x軸に"X-axis"という名前を付けフォントサイズを20にする(このままでは日本語は使えません)
plt.ylabel("Y", fontsize=20) # y軸に"Y-axis"という名前を付けフォントサイズを20にする(このままでは日本語は使えません)

plt.show()
In [12]:
# X軸、Y軸の表示範囲の設定
import math
import matplotlib.pyplot as plt
x, y = [],[]
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))

plt.plot(x, y)
v = [0, 2*math.pi, -1, 1] # x,y軸の範囲指定するためのリストv=[x_min, x_max, y_min, y_max]を用意
plt.axis(v) # 軸の設定を行う

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)

plt.show()
In [13]:
# X軸とY軸のスケールを一致させる
import math
import matplotlib.pyplot as plt
x, y = [],[]
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))

plt.plot(x, y)
plt.axis("scaled") # X軸とY軸のスケールを一致させる
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)

plt.show()
In [14]:
# cos関数も同時に表示し,凡例を加える
import math
import matplotlib.pyplot as plt
x, y, z = [], [], [] # cos関数の値を代入するリストzを用意
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))
    z.append(math.cos(math.radians(i))) # ラジアンに変換したx[i]をcos関数の引数としリストzへ付け加える(要するに$z_i=\cos{x_i}$)

plt.plot(x, y, label="$y=\sin{x}$") # y=sinxに凡例を付ける
plt.plot(x, z, label="$y=\cos{x}$") # y=cosxに凡例を付ける
plt.axis("scaled")
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)  

plt.legend() # 凡例を表示

plt.show()
In [15]:
# 線の色と太さの変更
import math
import matplotlib.pyplot as plt
x, y, z = [], [], [] 
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))
    z.append(math.cos(math.radians(i))) 

plt.plot(x, y, color="r", linewidth=4, label="$y=\sin{x}$") # 線の色をredに,線の太さを4にする
plt.plot(x, z, color="k", linewidth=2, label="$y=\cos{x}$") # 線の色をblackに,線の太さを2にする
plt.axis("scaled")
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)  

plt.legend()

plt.show()
In [16]:
# マーカーや線種の指定
import math
import matplotlib.pyplot as plt
x, y, z = [], [], [] 
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))
    z.append(math.cos(math.radians(i))) 
    
plt.plot(x, y, color="r", marker="o", linestyle="-", label="$y=\sin{x}$") # 色をred,マーカー形を"o",線種を"-"と指定した
plt.plot(x, z, color="k", marker="d", linestyle="", label="$y=\cos{x}$") # 色をblack, マーカー形を"d", 線種をなしと指定した
plt.axis("scaled")
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)  

plt.legend()

plt.show()
In [17]:
# マーカーや線種の指定 簡略化
import math
import matplotlib.pyplot as plt
x, y, z = [], [], [] 
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))
    z.append(math.cos(math.radians(i))) 
    
plt.plot(x, y, "ro-",  label="$y=\sin{x}$")
plt.plot(x, z, "kd",  label="$y=\cos{x}$")

plt.axis("scaled")
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)  

plt.legend()

plt.show()
In [18]:
# グラフ画像の出力
import math
import matplotlib.pyplot as plt
x, y, z = [], [], [] 
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))
    z.append(math.cos(math.radians(i))) 
    
plt.plot(x, y, "ro-",  label="$y=\sin{x}$")
plt.plot(x, z, "kd",  label="$y=\cos{x}$")

plt.axis("scaled")
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)  

plt.legend()

plt.savefig("it06_fig1.pdf") # 画像pdfとして出力・保存する
In [19]:
# 複数グラフの表示
import math
import matplotlib.pyplot as plt

x, y, z = [], [], [] 
for i in range(0, 396, 18):
    x.append([math.radians(i)])
    y.append(math.sin(math.radians(i)))
    z.append(math.cos(math.radians(i))) 
    
plt.subplot(2, 1, 1) # 画面を2行1列に分割し1(上側)に出力するという事
plt.plot(x, y, "ro",  label="$y=\sin{x}$")

plt.axis("scaled")
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X-axis", fontsize=20)
plt.ylabel("Y-axis", fontsize=20)  

plt.legend()

plt.subplot(2, 1, 2) # 画面を2行1列に分割し2(下側)に出力するという事
plt.plot(x, z, "kd",  label="$y=\cos{x}$")

plt.axis("scaled")
v = [0, 2*math.pi, -1, 1]
plt.axis(v) 

plt.xlabel("X", fontsize=20)
plt.ylabel("Y", fontsize=20)  

plt.legend()

plt.show()

問題

各自それぞれ自分の好きな関数を2つ用意し上述のように複数グラフを作成して下さい.軸の範囲,軸のラベル,凡例,プロットの色など工夫して見やすくして下さい.

6.2 データを読み込みとグラフ表示

前回学んだファイルの入出力方法と今日学んだmatplotlibを用い,データを読み込み解析しグラフ化してみましょう. ここでは毎日の日経平均株価の終値データを解析してみます(データはここ).

In [20]:
# このプログラムはスマートではありません(皆さんが今持っている知識のみで作ってます)
import matplotlib.pyplot as plt 

year = 2015

in_file1 = open("I101_{}.csv".format(year), "r", encoding='shift-jis')
list1, v_fin, v_max, v_min, v_date =[], [], [], [], []

i=0
for line in in_file1:
    if i > 1 :
        line = line.replace("\n", "") # "\n"を削除
        list1.append(line.split(",")) # ","で分割
        v_fin.append(float(list1[i-2][3])) # 株価の終値データをfloat型に変換し,
        v_date.append(i-2) # x軸としてデータの順番を用いる(年月日を軸にするためにはdatetimeモジュールを使う必要あり)
    i += 1

in_file1.close()

v_fin.reverse() # 株価の終値データを古い順にする

plt.subplot(2, 1, 1) 
plt.plot(v_date, v_fin, "g-")
plt.title("INDEX NIKKEI {}".format(year))

# 前日の株価との差を取ってみる
dif_fin, dif_date = [], []
for i in range(1, len(v_fin)):
    dif_fin.append(v_fin[i] - v_fin[i-1])
    dif_date.append(i-1)

plt.subplot(2, 1, 2) 
plt.plot(dif_date, dif_fin, "b-")    
plt.title("The difference between the stock price of every other day(DST)")

plt.tight_layout()
plt.show()

# 前日との株価の差の分布は?
plt.hist(dif_fin, bins=20, range = (-1000, 1000))
plt.title("Histgram of DST")
plt.xlabel("Price Difference")
plt.show()

応用問題

気象庁のサイトからは様々な過去の気象データを自由にDLすることができます.例えば,このデータは1915年から2015年までの5日間平均気温の時系列データです.このデータを自由に加工しデータ解析して楽しんで下さい.

6.3 グラフのアニメーション

matplotlibは動的なアニメーションを作ることもできます。そして、それをJupyter Notebook上で埋め込んで表示しさらに.mp4形式で保存することもできます。ただ、私がイロイロ試した範囲ではIPythonmatplotlibJupyter Notebookのバージョン依存で上手く動かないもしくは表示されたい場合があります。以下の手法ではおそらく皆さんの環境下で動作すると思っておりますが、動かなかったらドンマイ(2017/11/09)。

In [21]:
import numpy as np
import matplotlib.pyplot as plt

from matplotlib import animation, rc
from IPython.display import HTML #Jupyter notebookでアニメ表示するには現在ではこれが重要

fig, ax = plt.subplots()

ax.set_xlim(( 0, 2))
ax.set_ylim((-2, 2))

line, = ax.plot([], [], lw=2) #空のデータ(x, y)を用意する line,はタプル
plt.close()

def init():
    line.set_data([], [])
    return (line,) #

def animate(i):
    x=np.linspace(0, 2, 1000)
    y=np.sin(2*np.pi*(x-0.01*i))
    line.set_data(x, y)
    return (line,)

rc('animation', html='html5')
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=20, blit=True)
In [22]:
anim
Out[22]: