matplotlibで図形
matplotlibで図形を描く方法。
plot()関数が呼ばれると背後でfigure()が呼ばれ、続いてaxes()が呼ばれてfigureの中に軸をつくる。
plot()関数を呼ばずにfigure()やaxes()で図、軸を設定できる。
import matplotlib.pyplot as plt c1 = plt.Circle((0, 0), radius=1, fc="yellow", ec="r") ax = plt.gca() ax.add_patch(c1) plt.axis("scaled") plt.show()
○figure()関数
Figureオブジェクトを作る。
Definition :
figure(num=None, # autoincrement if None, else integer from 1-N figsize=None, # defaults to rc figure.figsize dpi=None, # defaults to rc figure.dpi facecolor=None, # defaults to rc figure.facecolor edgecolor=None, # defaults to rc figure.edgecolor frameon=True, FigureClass=Figure, **kwargs)
num | figure番号。整数または文字列のオプション引数でデフォルトはNone。もしnumが与えられなければ、新しいfigureを作り、figure番号を1増やす。figureオブジェクトはこの番号をnumber属性として保持する。もしnumが与えられ、すでに存在しているfigure番号だった場合は、そのfigureオブジェクトをアクティブにし、参照を返す。存在しないfigure番号のときは、新規のfigureオブジェクトを作成し、その参照を返す。numが文字列のときはウィンドウのタイトルがnumになる。 |
---|---|
figsize | (幅, 高さ)の整数のタプルで単位はインチ。デフォルトはrc figure.figsize |
dpi | figureの解像度。整数で、デフォルトははrc figure.dpi |
facecolor | 背景色。デフォルトはrc figure.facecolor |
edgecolor | 枠の色。デフォルトはrc figure.edgecolor |
返り値 | figureオブジェクト |
---|
○axes()関数
Figureオブジェクトに座標軸を付け加える
parameter | 値 | 内容 |
---|---|---|
facecolor | color | 軸の背景色 |
frameon | True or False | 枠を表示するか |
sharex | otherax | 他の軸とxaxis属性を共有するか |
sharey | otherax | 他の軸とyaxis属性を共有するか |
polar | True, False | 極座標を使うか |
aspect | "equal", "auto", num | アスペクト比x/y。"equal"は1:1 |
○axis()メソッド
要素数4のタプルを引数としてaxis()メソッドを呼ぶと、座標軸の範囲を変更できる。
引数 | 内容 |
---|---|
なし | 現在の座標軸の範囲を(xmin, xmax, ymin, ymax)のタプルで返す。 |
"off" | 座標軸を表示しない |
"equal" | 円が円に見える。 |
"scaled" | 座上軸の両端の自動調整 |
"tight" | 余白を小さく? |
"image" | データの範囲に合わせる |
"auto" | 非推奨 |
"normal" | 非推奨 |
"square" | x軸の範囲(xmax-xmin)とy軸の範囲を等しくする |
fig = plt.figure() ax =plt.axes() print(plt.axis()) # (0.0, 1.0, 0.0, 1.0) v = (0, 2, 0, 3) plt.axis(v) plt.show()
x軸の範囲が0~2、y軸の範囲が0~3になっている。
gcf()関数:現在のFifureへの参照。オブジェクトがない場合は作成する。
gca()関数:現在のAxesへの参照。オブジェクトがない場合は作成する。
○ax.set_aspect()関数
グラフのアスペクト比を設定する。
○円plt.Circle以外にもいろいろな図形が書ける。
Ellipse, Polygon, Rectangleなどなど
参考:
patches — Matplotlib 2.0.1 documentation
csvライブラリ
csvモジュールの使い方について。
以下の内容のtest.csvを準備しました。
1,20 2,30 3,40 4,50
○csvファイルの読み取り
(1)各行はリストとして読み込まれる。
import csv with open("test.csv", "r") as f: data = csv.reader(f) print(data) <_csv.reader object at 0x...> for i in data: # 各行がリストになっている print(i) # ['1', '20'] # ['2', '30'] # ['3', '40'] # ['4', '50']
(2)joinで見やすく。
with open("test.csv", "r") as f: data = csv.reader(f) print(data) for i in data: print(", ".join(i)) # 1, 20 # 2, 30 # 3, 40 # 4, 50
csv.reader()の引数になるのは、ファイルオブジェクトまたはリスト
(3)読み飛ばしたい行があるときはnext()する。
with open("test.csv", "r") as f: data = csv.reader(f) next(data) # 1行読み飛ばす for i in data: print(", ".join(i)) # 2, 30 # 3, 40 # 4, 50
(4)読み飛ばす行をヘッダーなどとして使用するときは代入をしておく。
with open("test.csv", "r") as f: data = csv.reader(f) header = next(data) # 1行読み飛ばし、headerに代入 print(header) # ['1', '20'] for i in data: print(", ".join(i)) # 2, 30 # 3, 40 # 4, 50
○csvファイルの書き込み
newline=""とオプションを入れないと、空白行が追加されてしまう。
(1)
import csv with open('test.csv', 'w', newline="") as f: writer = csv.writer(f) writer.writerow([1] + [20]) writer.writerow([2, 30]) for i in range(3, 5): writer.writerow([i, (i + 1) * 10])
(2)
data =[[1, 20], [2, 30], [3, 40], [4, 50]] with open('test.csv', 'w', newline="") as f: writer = csv.writer(f) writer.writerows(data)
matplotlibの色名一覧
この色名一覧はpythonで書かれていて、同じページにコードも載っています。
あとでゆっくりコードを読んでみようと思います。
# coding: utf-8 from __future__ import division import matplotlib.pyplot as plt from matplotlib import colors as mcolors colors = dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS) # (HSV形式,色名)というタプルに直し、Hをキーにしてソートしたリストにする by_hsv = sorted((tuple(mcolors.rgb_to_hsv(mcolors.to_rgba(color)[:3])), name) for name, color in colors.items()) # sortしたタプルのリストから、色名だけを抜き出したリストを作る sorted_names = [name for hsv, name in by_hsv] n = len(sorted_names) # 8色 + 148色 = 全156色 ncols = 4 # 列数を4にする。他の数でもよい nrows = n // ncols + 1 # 行数を計算 fig, ax = plt.subplots(figsize=(8, 5)) # 横8インチ、縦5インチ # Get height and width X, Y = fig.get_dpi() * fig.get_size_inches() h = Y / (nrows + 1) # 1マスの縦のドット数 w = X / ncols # 1マスの横のドット数 for i, name in enumerate(sorted_names): col = i % ncols # 0番 1番 2番 3番 row = i // ncols # 4番 5番 6番 7番 ...のように割り振る y = Y - (row * h) - h # 表示するy座標 xi_line = w * (col + 0.05) # 長方形の左端のx座標 xf_line = w * (col + 0.25) # 長方形の右端のx座標 xi_text = w * (col + 0.3) # 色名の文字列を表示するx座標 # 左よせで文字を表示 ax.text(xi_text, y, name, fontsize=(h * 0.8), horizontalalignment='left', verticalalignment='center') # hlines(横向きの直線)として色つきの長方形を表示 ax.hlines(y + h * 0.1, xi_line, xf_line, color=colors[name], linewidth=(h * 0.6)) ax.set_xlim(0, X) ax.set_ylim(0, Y) ax.set_axis_off() fig.subplots_adjust(left=0, right=1, top=1, bottom=0, hspace=0, wspace=0) plt.show()
わからないことが多すぎるので、いろいろ確認してみた。
・mcolors.BASE_COLORS :
8つの基本色。アルファベット1文字で表す。
色名:RGBの辞書型になっている。
print(mcolors.BASE_COLORS) # {'y': (0.75, 0.75, 0), 'm': (0.75, 0, 0.75), 'r': (1, 0, 0), # 'c': (0, 0.75, 0.75), 'k': (0, 0, 0), 'g': (0, 0.5, 0), # 'w': (1, 1, 1), 'b': (0, 0, 1)}
・mcolors.CSS4_COLORS
148色の(色名:16進コード)の辞書型
print(len(mcolors.CSS4_COLORS)) # 148 print(mcolors.CSS4_COLORS) # {'oldlace': '#FDF5E6', 'limegreen': '#32CD32', 'palevioletred': '#DB7093', # 'mintcream': '#F5FFFA', 'rosybrown': '#BC8F8F', 'blueviolet': '#8A2BE2', # 'lime': '#00FF00', 'orange': '#FFA500', 'mediumorchid': '#BA55D3', ...
参考:
color example code: named_colors.py — Matplotlib 2.0.1 documentation
matplotlibで散布図
matplotlibで散布図を描く方法について。
Definition :
plt.scatter( x, y, # x座標, y座標の配列 s=None, # マーカーのサイズ c=None, # マーカーの色 marker=None, # マーカーの形 cmap=None, # cがfloat型のときのカラーマップ norm=None, # cをfloat型配列にした時の規格化インスタンス指定 vmin=None, vmax=None, # 最大・最小 alpha=None, # 透明度 linewidths=None, # 線の太さ verts=None, edgecolors=None, # 線の色 hold=None, data=None, **kwargs)
色名一覧はここ
・乱数で100個の点を描く
import numpy as np import matplotlib.pyplot as plt x = np.random.rand(100) y = np.random.rand(100) plt.scatter(x, y) plt.show()
・マーカーをひし形にして、色を付ける。
x = np.random.rand(100) y = np.random.rand(100) plt.scatter(x, y, s=100, c="orange", edgecolor="red") plt.show()
・直線、軸、タイトルつき。
import numpy as np import matplotlib.pyplot as plt #日本語を使う場合は以下の2行でフォントを準備 from matplotlib.font_manager import FontProperties fp = FontProperties(fname='C:\WINDOWS\Fonts\msgothic.ttc', size=14) x = np.arange(20) y = x + np.random.rand(20)*4 plt.scatter(x, y, s=50, marker="x", c="red", linewidth=1) plt.plot([0, 19], [2, 21], c="blue") #直線の描画 plt.title("散布図", fontproperties=fp) plt.xlabel("x軸", fontproperties=fp) plt.ylabel("y軸", fontproperties=fp) plt.show()
chars = "^<>vo+d" x = np.random.rand(100) y = np.random.rand(100) markers = [chars[i%7] for i in range(100)] for i in range(100): plt.scatter(x[i], y[i], marker=markers[i]) plt.show()
x = np.random.rand(10000) y = np.random.randn(10000) plt.scatter(x, y, alpha=0.2) plt.show()
x = np.random.randn(10000) y = np.random.randn(10000) plt.scatter(x, y, alpha=0.2) plt.show()
カラーマップを使う。
x = np.random.rand(100) y = np.random.rand(100) col = np.linspace(0, 1, 100) plt.scatter(x, y, c=col, cmap="spring") plt.colorbar() #カラーバーの表示 plt.show()
カラーマップの一覧はここに。
参考:
エラー
構文解釈時のよくあるエラーについて。
AttributeError:
・'~' object has no attribute '~'
属性名、メソッド名などが間違っている。存在しないのに呼び出した。
lとrや大文字小文字などスペルミスを見直す。
ドットを打ち込んで属性の候補一覧からTAB補完で選ぶとミスが減る。
属性の候補一覧に載っていない場合は変数などの型がミスっているかも。
NameError 変数名などが間違っている。
・name '~' is not defined
代入(assign)前の変数を利用しようとした。
変数をdelしてしまった。
変数名のタイプミスなど。
IndentationError:
・expected an indented block
必要な部分にインデントされていない。
def, if, for, while, classなどの次の行。
・unexpected indent
インデントしてはいけない部分でインデントしてしまった。
IndexError インデックスミス
・list index out of range
インデックスの範囲外を指定してしまった。
print(len(list1))などで要素数を確認する。
最初の要素は[1]ではなく[0]
TypeError 型が合ってない
・'list' object is not callable
リストオブジェクトを関数として扱ってしまっている。
・list1[0]とするのをlist1(0)としている。
・何らかの関数をリストで上書きしてしまっている。
list=[1, 2, 3]などと、組み込みの関数名を変数名にするとミスが多い。
・'int' object is not callable
intオブジェクトを関数として扱ってしまった。
数学の式で(x + y)(x - y)はpythonでは(x + y)*(x - y)
SyntaxError
・invalid character in identifier
全角スペース、タブなどが混入。webのコピペでよくある。
・invalid syntax
その他のエラー。
エラーよりも前の行で()の対応が合っていない。とくにclosing parenthesis「)」
・EOL while scanning string literal
文字列のクオーテーションが閉じられていない。
・Missing parentheses in call to 'print'
print文は()を付ける。
・unexpected EOF while parsing
構文解釈中にプログラムの最後まで読んでしまった。
最終行付近で閉じ括弧をわすれていたり。
pythonで統計
pythonを使って統計処理をします。
○1変数の基本統計量
要素数
平均mean
範囲
最頻値mode
中央値median
分散variance
標準偏差standard deviation
# -*- coding: utf-8 -*- from collections import Counter def mean(seq): return sum(seq) / len(seq) # 平均=合計/要素数 def range_(seq): return min(seq), max(seq) # 範囲:(最小値, 最大値) def mode(seq): c =Counter(seq).most_common() # (要素, 頻度)というタプルの頻度順リスト max_f = c[0][1] # c[0]:最頻出要素 modes = filter(lambda x:x[1]==max_f, c) # 頻度1位を全て抜き出す return [i[0] for i in modes] # 値のみをリスト内包表記にして返す def median(seq): s = sorted(seq) if len(s) % 2 == 0: # 要素が偶数個なら2つの平均 return (s[len(s) // 2] + s[(len(s) // 2) - 1]) / 2 else: return s[len(s) // 2] # 要素が奇数個なら中央の値 def sigma(seq): # 分散 m = mean(seq) total = sum(map(lambda x:(x - m)**2, seq)) return total / len(seq) def sd(seq): return sigma(seq) ** 0.5 # 標準偏差=sqrt(分散) def stat(seq): if len(seq) == 0: print("要素がありません") else: print("要素数:", len(seq)) print("平均:", round(mean(seq), 2)) # 小数第2位までで表示 print("範囲:", range_(seq)) print("最頻値:", *mode(seq)) print("中央値:", median(seq)) print("分散:", round(sigma(seq), 2)) print("標準偏差:", round(sd(seq), 2)) list1 = [100, 60, 50, 70, 100] # タプルでもOK stat(list1) # 要素数: 5 # 平均: 76.0 # 範囲: (50, 100) # 最頻値: 100 # 中央値: 70 # 分散: 424.0 # 標準偏差: 20.59
○2変数の基本統計量
・相関係数
公式:
# correlation coefficient def corr(x, y): if len(x) != len(y): return "different length" sx = sum(x) sy = sum(y) sx2 = sum(map(lambda x:x**2, x)) sy2 = sum(map(lambda x:x**2, y)) sxy = sum(map((lambda x, y:x*y), x, y)) n = len(x) try: return (n*sxy-sx*sy)/((n*sx2-sx**2)*(n*sy2-sy**2))**0.5 except: return 0 x = [1, 2, 3] y = [5, 5, 6] print("相関係数:", corr(x, y)) # 相関係数: 0.8660254037844387
pythonで円周率を求める
pythonで円周率を求めるアルゴリズム
○ライプニッツの方法
収束が遅い。
100万回計算して、6桁くらい。
pi4 = 0 for i in range(1000000): pi4 += (1 / (i * 4 + 1) - 1 / (i * 4 + 3)) print(pi4 * 4) # 3.141592153589902
○区分求積を使う。
収束が速い。
25回の計算で15桁くらいまで出ます。
pi4 = 0 for i in range(1, 50, 2): pi4 += (-1)**(i//2) * (1/2**i + 1/3**i) / i print(pi4 * 4) # 3.1415926535897922
○ガウス・ルジャンドルの方法
収束が非常に速く、4回も計算すれば15桁まで出ます。
a, b, t, p = 1, 1/2**0.5, 1/4, 1 for i in range(4): a, b, t, p = (a+b)/2, (a*b)**0.5, t-p*((b-a)/2)**2, p*2 print((a + b)**2 / (4 * t)) # 3.1405792505221686 # 3.141592646213543 # 3.141592653589794 # 3.141592653589794
○モンテカルロ法
乱数を使って円周率を求める方法。
原点中心、半径1の円とその円に外接する正方形の面積比がπ/4であることを利用し、1万個の座標を乱数で生成して円周率を求めてみた。
サンプルコード(1) randomモジュールで。
import random inner = 0 for i in range(10000): x, y = random.random(), random.random() if x**2 + y**2 < 1: inner += 1 print(inner *4 / 10000) # 3.1446
サンプルコード(2) NumPyのrandomで。
np.random.seed(1) # 乱数の初期化。好みの数で。 arr = np.random.rand(2, 10000) # 2行10000列の乱数ndarray distance = (arr**2).sum(axis=0) # 全要素を2乗し縦に合計すると原点からの距離 count = (distance < 1).sum() # 距離が1未満か判断しTrueの個数を調べる print(4 * count / 10000) # 3.1348
1万個の散布図を描くとキャンバスが埋まってしまうので、1000個で描画
import numpy as np import matplotlib.pyplot as plt c1 = plt.Circle((0, 0), radius=1, fc="None", ec="r", linewidth=3) ax = plt.gca() ax.add_patch(c1) plt.axis("scaled") plt.xlim(0, 1) plt.ylim(0, 1) x = np.random.rand(1000) y = np.random.rand(1000) plt.scatter(x, y, marker="x") plt.show()
○逆三角関数を使う方法
cos(π)=-1なので
π=arccos(-1)
import math print(math.acos(-1)) # 3.141592653589793