matplotlib.pyplot – axesとsubplotによる複数グラフの表示

概要

1つのfigureの中に複数のaxesを表示する方法には、add_subplot()メソッド、subplots()メソッドの2通りがある。

add_subplot()による方法

Figure.add_subplot()は既存のfigureオブジェクトにsubplotを追加してAxesオブジェクトを生成する。

add_subplot()
figureに1つのAxesオブジェクトを生成
add_subplot(pos)
posは行数・列数・位置を表す3桁の整数。例えば234なら、2行3列のうち4番目の図。各数は当然10未満でなければならない。
add_subplot(nrows, ncols, index)
上記のposを分解して指定。行数・列数が多いときに使える。

subplots()による方法

Figure.subplots()は行数と列数を指定して各位置のaxesを配列として一度に生成する。

subplots(nrows=1, ncols=1, figsize=(6.4, 4.8))
nrowsncolssubplotの行数・列数。

戻り値はaxesの配列だが、行数・列数によって配列の次元が違ってくるので注意。

行数・列数とも1の場合(あるいはnrows、ncolsを省略した場合) Axesオブジェクトが1つ生成される。
行数・列数のいずれかが1の場合 1次元のAxesオブジェクトの配列が生成される。
行数・列数とも1より大きい場合 nrows×ncolsのサイズで2次元のAxesオブジェクトの配列が生成される。

行や列のぶち抜きグラフを描きたいとき

以下のようなグラフを描きたいときの方法はこちら

subplotの間隔や位置調整

figure内にsubplotで配置されたグラフの間隔やマージンを調整するにはsubplots_adjust()メソッドを用いる。

詳細な使い方はこちらを参照。

 

matplotlib.pyplot – axesによる表示(グラフエリアの表示要素)

概要

pyplotでグラフを描画する場合、pyplotのメソッドであるplotxlimを使うのが簡易だが、figureオブジェクトの下にaxesオブジェクトを生成して操作する方法がある。ここではaxesオブジェクトによる方法を整理してみた。

各メソッドの説明

axesオブジェクトの生成

ax = fig.add_subplot(arg)

figureオブジェクトからaxesオブジェクトを生成する。subplot()の引数argの指定方法には2通りある

なお、figureオブジェクトに属するaxesオブジェクトが1つの場合は以下のような指定もできる。

fig, ax = plt.subplots()

以後、グラフの描画やグラフエリアに対する表示オプションの設定は、得られたaxesオブジェクトのメソッドで行う。

グラフタイトル

axes.set_title(label[, loc])

文字列labelをグラフ上部に表示する。表示位置はloc="left"/"center"/"right"で指定(デフォルトは"center")

軸の設定

軸ラベル

axes.set_xlabel(label)
axes.set_ylabel(label)

文字列labelをx軸/y軸のラベルとして設定する。

set_xlabel()/set_ylabel()~軸のラベル

軸のスケール

axes.set_xscale(scale)
axes.set_yscale(scale)

軸のスケールを設定する。スケールの種類は以下の通り。

  • 'linear':通常の線形軸
  • 'log':対数軸
  • 'symlog':負の領域も含めた対数軸(−log (−x) for x < 0)
  • 'logit':?

軸の範囲

axes.set_xlim(left, right)
axes.set_ylim(bottom, top)

x軸・y軸の上限・下限を設定する。引数指定の変化などはpyplotのメソッドと同様

軸目盛の設定

axes.set_xticks(ticks)
axes.set_yticks(ticks)

ticksのリスト等の要素で軸目盛を設定する。軸目盛のラベルを変更したい場合は、ticksと同じ要素数のlabelsで以下を実行する。

axes.set_xticklabels(labels)
axes.set_yticklabels(labels)

なお、軸のラベルを非表示にしたいときは、以下のように指定する。

軸目盛を非表示にしたいときは以下を指定。

軸の調整

  • 軸の表示位置はspines()で指定する
  • 複数グラフの外側だけに軸ラベル・目盛ラベルを表示するには、各AxesオブジェクトについてAxes.label_outer()を実行する

凡例

pyplot.legend(loc=location)

データに設定されたラベルで、locationで指定した位置に凡例を表示する。locationの指定方法はpyplot.legendと同じ

詳細はpyplot – legendを参照。

格子

pyplot.grid(True/False)

Trueを指定すると、軸目盛に対応した格子が描かれる。

水平線・垂直線

axes.hlines([y, xmin, xmax, colors='k', linestyles='solid', label='']
axes.vlines([x, ymin, ymax, colors='k', linestyles='solid', label='']

指定した位置に水平線・垂直線を描く。引数の指定方法はpyplot.legendと同じ

テキスト

axes.text(x, y, str, size=size, color=color)

指定した位置にstrを表示させる。

参考サイト

pyplotpltを使う方法、axesaxを使う方法などがネット上にもそれぞれ存在していたが、以下の記事がたいへん参考になった。感謝したい。

早く知っておきたかったmatplotlibの基礎知識・・・

 

 

matplotlib.pyplot – figure~複数の図の描画

概要

pyplot.figure()は、実行のたびに新たなfigureオブジェクトを生成する。コンソールからの実行環境下では、各figureオブジェクトは別々のウィンドウとして表示され、それぞれにファイルへの保存が可能。

以下の例では、2つのfigureオブジェクトを生成し、それぞれにグラフをプロットし、それらをファイルに保存している。

figureで生成される図のサイズはfigsize=(width, height)で指定し、width, heightはインチ単位で指定する。省略した場合のデフォルトサイズは、6.4in×4.8in。

なお、figureオブジェクトを生成してグラフを描画する場合、直接figureに対してではなく、その中にaxesオブジェクトを追加して操作するのが通常。

matplotlib_pyplot_fig_1.png

matplotlib_pyplot_fig_2

 

matplotlib.pyplot – subplotによる複数グラフの描画

概要

pyplot.subplot()によって、一つのウィンドウに複数のグラフを描画できる。

subplot(rows, cols, positon)
subplot(rcp)

rowsでグラフの行数、colsで列数を指定。positionはrows*colsの中での描画位置を1つの数値で指定し、1行1列目→1行2列目→・・・→2行1列目→2行2列目の順番に1から1つずつ増えていく。

ここで引数指定に2つの方法があって、rows, col, positionをそれぞれ1つの数値として指定する方法と、rcpの形で1つの数値として指定する方法がある。たとえば2行3列のグラフエリアの2行2列目を指定する場合は(2, 3, 5)(235)となる。

以下の例は、2×2のグラフを描画する例。

 

matplotlib.pyplot – グラフエリアの表示要素

概要

pyplotで直接グラフを描画する際の基本的なオプションの例示。

各オプションの説明

グラフタイトル

pyplot.tytle(label[, loc])

文字列labelをグラフ上部に表示する。表示位置はloc="left"/"center"/"right"で指定(デフォルトは"center")

軸ラベル

pyplot.xlabel(label)
pyplot.ylabel(label)

文字列labelをx軸/y軸のラベルとして表示する。

軸の範囲

pyplot.xlim(left, right)
pyplot.ylim(bottom, top)

x軸・y軸の上限・下限を設定する。設定は2つの変数で与えるか、以下のようにタプルで与えてもよい。

pyplot.xlim((left, right))

また、上下限のいずれか1つの値を指定し、他方の値を保持したまま値の変更が可能。

pyplot.xlim(right=1)
pyplot.ylim(bottom=-1)

引数なしで実行すると、上限・下限の値がタプルで返される。

left, right = pyplot.xlim()

軸目盛の設定

pyplot.xticks(ticks[, labels])
pyplot.yticks(ticks[, labels])

リストなどで与えた値を軸目盛とする。labelsticksと同じ要素数で与えると、その内容が軸目盛のラベルに置き換えられる。

凡例の表示

pyplot.legend(loc=location)

データに設定されたラベルで、locationで指定した位置に凡例を表示する。

locationは文字列か整数のコードで以下のように指定。

location string location code
‘best’ 0
‘upper right’ 1
‘upper left’ 2
‘lower left’ 3
‘lower right’ 4
‘right’ 5
‘center left’ 6
‘center right’ 7
‘lower center’ 8
‘upper center’ 9
‘center’ 10

格子の表示

pyplot.grid(True/False)

Trueを指定すると、軸目盛に対応した格子が描かれる。

水平線・垂直線の表示

pyplot.hlines([y, xmin, xmax, colors='k', linestyles='solid', label='']
pyplot.vlines([x, ymin, ymax, colors='k', linestyles='solid', label='']

たとえばhlinesの場合、水平線を引くyの値をリスト等で与え、xminxmaxの間に線を描く。colorsは線の色、linestylesは線のスタイルで'solid', 'dashed', 'dashdot', 'dotted'のいずれか。

colorslinestylesは、1つ指定した場合は全ての水平線/垂直線に適用されるほか、yの要素数にあわせて個別に指定することもできる。

colorscolorlinestyleslinestyleと単数形で指定しても実行される。

 

 

numpy – arange, linspace~数列の生成

numpy.arange()~間隔を指定した数列の生成

引数・戻り値

numpy.arange([start, ]stop, [step, ]dtype = None)

引数 概要
start int/float 数列の開始値。省略可(デフォルトは0)
stop int/float 数列の終了値。省略不可。
step int/float 数列の間隔。省略可(デフォルトは1)。
dtype dtype 生成される数列のデータ型。指定しない場合は引数の型が適用される。

戻り値:開始値startからstepずつ増加し、stop未満の数列のndarray

引数の指定例

必ず以下のように指定する。numpy.arange(stop=5, step=2)のような指定はできない。

numpy.arange(stop)
0以上stop未満で増分1の数列を返す。数列の型は引数の型による。
numpy.arange(start, stop)
start以上stop未満で増分1の数列を返す。数列の型は引数の型による。
numpy.arange(start, stop, step)
startから始まり、stepずつ増加/減少し、stepの手前までの数列を返す。数列の型は引数の型による。

その他

降順の数列

stepを負の値にして降順の指定も可能。この場合はstart≥n>endの範囲となる。

実数列

stepを指定して実数の列も作れる。

ただしデフォルトでstart=0(0.0)step=1(1.0)なので以下のような挙動になる。

dtypeによる型指定

dtypeで強制的に型を指定可能。

numpy.linspace()~個数を指定した数列の生成

引数・戻り値

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

引数 概要
start int/float 数列の開始値。省略不可。
stop int/float 数列の終了値。省略不可。
num int 数列の要素数。省略可(デフォルトは50)。
endpoint bool stopを要素に含むかどうかを指定。Trueで含み、Falseなら含まない。省略可(デフォルトはTruestopを含む)。
retstep bool 戻り値として配列に加えて公差を返すかどうかを指定。Trueで配列を第1要素、公差を第2要素とするタプルを返し、Falseなら配列のみを返す。
dtype dtype 生成される数列のデータ型。指定しない場合はfloatが適用される。

戻り値:startからstopまでをnum等分した数列のndarray

引数の指定例

numpy.linspace(start, stop)
startから始まりstopで終わる50個の数列を返す。
numpy.linspace(start, stop, num)
startから始まりstopで終わるnum個の数列を返す。
numpy.linspace(start, stop, num, endpoint=False)
startから始まりstopの手前で終わるnum個の数列を返す。

その他

dtypeによる型指定

dtype=intと指定して、整数列を生成できる。

ただし分割個数を適切に指定しないと、変な結果になる。

retstepを指定した公差の取り出し

retstep=Trueと指定すると、第1要素に数列のndarray、第2要素に公差を持つタプルが返される。

 

 

Python3 – forループの最初と最後だけ処理を変えたい

やりたいこと

たとえば多数の計算結果を表示するとき、リストなら最初だけ"["がついて、各要素の後ろに", "が付加されて、最後の要素だけそのカンマがなくて"]"が表示される。このような処理をいろいろな形で実装したいというような場合。

単純に考えると次のように格好が悪い。

これを、<0, 1, 2, 3, 4>のように末尾だけ表示方法を変えたい、さらには、何個かごとに改行させて、2行目以降の行頭を1行目と変更したいときの処理を考える。

インデックスを利用する方法

1行で表示する場合

以下の例では、enumerateでコレクションのインデックスを取り出して、その値によって処理を分けている。行頭"<"の処理はforループの前でやってもよいが、次の複数行表示の準備としてif文で判定している。

複数行に分けて表示する場合

長いリストや多次元の配列などを複数行に分けて表示したい場合、行ごとの行末文字も変わってくる。そのような処理をforループで書いてみた。

ジェネレーターを使う方法

ジェネレーターを使った方法。このジェネレーターは、各要素のprefix、本体要素、suffixの3つを返す。

1文字目だけ処理を変えるため、コレクションをイテレーターとし、ループに入る前に最初の要素を取り出している。next()関数でイテレーターの内容を取り出すと、その後のforループでは以降の要素が順次取り出されることを利用している。

prefixは最初だけ"<"を使い、その後は""としてprefixなしとして扱っている。

1行で表示する場合

複数行に分けて表示する場合

複数行に分ける場合、1行当たりの要素数を設定し、カウンターで要素位置を検出している。カウンターの値から先頭要素と判定した場合にprefixを" "とし、その他の場合は""としている。

 

Python3 – yield文によるジェネレーターの実装

return文の確認

yield文はreturn文と同様に関数の中で使われ、戻り値を指定するが、その挙動は全く異なる。

まず準備として、通常のreturn文を持つ関数の動作を確認。呼び出されるたびに常に関数の先頭からreturn文まで実行される。

yield文にするとジェネレーターが生成される

このreturn文をyield文に変更してみると、関数の戻り値を返すのではなく、この関数がジェネレーターオブジェクトのコンストラクターとなっている。

ジェネレーターオブジェクトには、(Python3では)__next__()メソッドがあって、ジェネレーターで生成された値を順次取り出してくれる。そこで上のfunc1()でジェネレーターのインスタンスを生成し、直接値を取り出してみる。

このジェネレーターは値を1つしか生成しないので、2つ目を取り出そうとするとStopIteration例外を投げる。

yield文によるジェネレーターの挙動

以下の例は、3つの値を返すジェネレーターの例で、確認のためにyield文の前の処理をprint文で表示させるようにしている。なお、ここでは__next__()メソッドの代わりに組み込み関数next()を用いている。

関数で生成されるのはジェネレーターでStopIterationを投げるので、次のようにfor文で使える。

yiled文とreturn文を混ぜた場合

関数の中でyield文を書くと、return文があってもジェネレーターが生成される。

ただしreturn文があるとそこでStopIterationが投げられる。このとき、return文で指定した戻り値が得られるようだが、ジェネレーターとしては無視されるらしい。

このジェネレーターをfor文で使うと、以下のようにreturn文の手前まで実行される。

実装の例

たとえば引数を与えて、その数以下であるフィボナッチ数列を返すジェネレーターを考える。

 

k平均法

概要

k平均法(k-means clustering)はクラスタリングの手法の1つで、与えられたデータ群の特徴と初期値に基づいて、データを並列(非階層)のクラスターに分類する。

ここではk平均法の簡単な例を実装したKMeansClusteringクラスによって、その挙動を確認する。

テストケース

基本形

2つのクラスターがある程度明確なケースで試してみる。一定の円内にランダムに点を発生させ、そのグループを2つ近づけた例。

以下のように、重なった部分は仕方がないが、かなり元のグループに近い分類となっている。

初期値を変えた場合

代表点の初期値を変えて実行してみる。

上記とはかなり離れた初期値を設定しても、解は同じになる。

収束解も上記と全く同じ値になる。

クラスターが不明確な場合

先の結果だけを見ると、かなり初期値がずれてもクラス分類は安定なように見える。

そこで次に、元々の分布に明確なクラス分けが見えない場合に3つのクラスターに分ける例を考える。

初期値1

初期値2

上記に対して初期値を変更。

データは同じだが、クラスター分けは違ってきている。

極端な例

次に、元の分布でクラスターが見いだせないような極端な場合を考える。

初期値1

代表点の初期値は縦に並んでおり、クラスターも縦方向に分割されている。

初期値2

全く同じデータで代表点の初期値を横に並べた場合、クラスター分けは大きく異なっている。

3クラスター

最後に、元のデータでクラスターがかなり明確な場合を試してみる。

初期値1

初期値が隅の方から始まっていても、3つのクラスターによく分かれている。

初期値2

初期値の場所や並びがかなり異なっていても、クラスター分けは安定している。

まとめ

k平均法は初期値によって解が変動するとされているが、明らかにクラスターが明確な場合には解は安定している。

ただしそのようなケースは、特徴量の数が少なく分布が一目瞭然の場合に相当するので、特徴量が多く一目ではそのクラスターがわかりにくいような場合には、やはり初期値の取り方に大きく影響されるものと考えられる。