Python – How to do what I want to do

ndarray関係

1次元配列の2次元化

1次元配列を単に2次元化

1次元配列を2次元一要素の行ベクトルにする方法。

  • np.array([a])と2次元で構築する
  • reshape(1, -1)で2次元1行の配列として変形

1次元配列の列ベクトル化

1次元配列を2次元の列ベクトルにする方法。hstack()などで列ベクトルを横に結合していくときに必要。

  • reshape(-1, 1)でn行1列の配列として変形

2つの1次元配列の結合

縦に積み重ねる

素直に実行するならvstack()を使うのがおすすめ。

  • vstack()は1次元配列のままで積み重ねられる
  • append()は1次元配列を2次元化する必要がある

列ベクトルとして横につなげていく

この場合はhstack()が意外にややこしく、c_が手軽。ただし列ベクトルを意識するならhstack()もアリ。

  • 1次元配列をreshape()で列ベクトル化し、hstack()を使う(1次元配列のままだと横1列に伸びるだけ)
  • c_を使う(1次元配列でも列ベクトル化されて結合される)

空のベクトルへの追加

1次元配列の縦方向への追加

縦方向に追加するならvstack()が全般によさそう。

empty((0, n), dtype=type)で空の配列を準備し、これにvstack()で1次元配列をそのまま追加していく。

1次元配列を列ベクトルとして横方向に追加

empty((n, 0), dtype=type)で空の配列を準備し、1次元配列をreshape()で列ベクトルに変形してhstack()で追加していく。

または、c_を使うとreshape()を使わなくてもそのまま列ベクトルとして追加してくれる。

多次元配列の1次元化

2次元以上の配列を1次元としたいときは、reshape(-1)を使う。

たとえばpyplotのsubplotで2次元の配列として得られたAxesオブジェクト(への参照)に対して全て同じ処理を施したいときに、以下のようにする。

条件による抽出

条件に合う要素を取り出す

条件式による要素の取り出しを参照。

条件に合う要素のインデックスを取り出す

1次元配列の条件に合う行を2次元配列から切り出す

特徴量データの配列のうち、特定のクラスに属するデータだけを取り出したいときなど。

インデックス配列の置き換え

例えばclass_name = np.array(["Class-0", "Class-1", "Class-2"])と定義されているとき、配列np.array([0 1, 2, 0])の各要素をインデックスとしてclass_nameの要素で置き換えたい(numpy.ndarray(['Class-0', 'Class-1', 'Class-2', 'Class-0'])を得たい)。

インデックス配列の置き換えを参照。

統計値の計算

min, max, argmin, argmax

1次元配列のmin()メソッド/max()メソッドを使うと、要素の中の最小値/最大値が得られる。また、argmin()メソッド/argmax()メソッドを使うと、最小の要素/最大の要素のインデックスが得られる。

2次元配列の場合は、a.reshape(-1).min()a.reshape(-1).argmin()などと同じ結果となる。

メソッドの引数でaxis=0を指定すると、各列ごとの最小値/最大値を要素とする1次元配列を得る。

axis=1を指定すると、各行ごとの最小値/最大値を要素とする1次元配列を得る。この場合、この配列を列ベクトルとして考えると対比がわかりやすい。

sum,mean

要素の和や平均を計算するsum()メソッド/mean()メソッドもmin()max()と同じように機能する。

1次元配列の場合。

2次元配列の場合は全要素で計算したスカラーを返す。

axis=0で列ごとに計算した結果を1次元配列で返す。

axis=1で行ごとに計算した結果を1次元配列で返す。この配列が列ベクトルだと解釈すると分かりやすい。

順列や組み合わせを得たい

概要

順列や組み合わせの結果としての要素のコレクションを得たいときは、itertoolsパッケージを使い、結果のイテレーターをforループなどで利用。

要素数(選び出す個数)指定のパラメーター名や省略時の挙動がそれぞれで異なっているので注意。

直積

itertools.product()で直積のイテレーターを得る。

順列

itertools.permutations()で順列のイテレーターを得る。

組み合わせ

itertools.combinations()で組み合わせのイテレーターを得る。

重複組み合わせ

combinations_with_replacement()で重複ありの組み合わせのイテレーターを得る。

 

インデックス配列の置き換え

表題だけではよくわからないが、以下のような場合に使う。

たとえばクラス分類のためのターゲットのデータセットが以下のように与えられているとする。

このとき、クラス0~2に対応する以下のような名前で表現したターゲット配列を得ることができるというもの。

順を追って考えてみるのに、まずnames配列から一つの要素を取り出す。

配列の要素をリストとすると、そのリストの要素をインデックスとみなして、インデックスに対応する元の配列の要素を並べた配列を返す。結果はリストではなくndarray。

配列の要素を配列としても同じように動作する。

これより、クラス分類のターゲット配列などが与えられたときに、これを番号ではなくクラス名などの配列に変換することができる。

なお、インデックス配列が2次元の場合は結果の配列も2次元となる。

 

ndarray – ブロードキャスト

1次元の場合

以下の配列を元の配列とする。

数値は1次元配列に拡張されて、要素ごとに演算される。

要素が1つの配列(リスト)は同じサイズの配列に拡張されて、要素ごとに演算される。

2次元の場合

以下の配列を元の配列とする。

数値は2次元配列に拡張されて、要素ごとに計算される。

要素が一つの配列は2次元に拡張されて、要素ごとに計算される。

列数と同じ要素数の1次元配列(リスト)は、同じ列数の2次元配列に拡張されて計算される。

行数と同じ要素数の列ベクトルは、同じ行数の2次元配列に拡張されて計算される。

 

Python/pyplot – 決定境界の描き方

決定境界の描き方として以前ループを使った泥臭い方法を考えたが、meshgridを使って数行で書けることを知ったのでまとめ。

結論としては以下の19~25行目の8行で、以下の手順で決定境界を書いている。

  1. 2つの特徴量の全領域をカバーする値をnumpy.linspace()で生成
  2. numpy.meshgrid()で2次元のグリッドに変換
  3. 各特徴量のメッシュグリッドを1次元に変形し、縦2列の配列化
  4. prediction()メソッドでその配列の各座標に対応する予測値を計算(結果は1次元配列)
  5. 結果の配列をmeshgridと同じ形状の2次元配列に変形
  6. contour/contourf()で決定境界を描画

具体的な変数の変形状況を要素数4の少ない例で示すと以下の通り。

まず、2つの特徴量の範囲の数列を生成する。

それらの数列を、meshgridで2次元配列に変形する。

予測モデルに与える変数は各特徴量を列とする2次元配列とする必要があるので、まず上の2次元配列をそれぞれ1次元に変形。この変形では、2次元配列の各行を連ねていった1行の配列を列ベクトルにした形になる。

次に2つの列ベクトルを横方向に並べて、総計算データ数×特徴量数(2)の2次元配列とする。

この配列の各座標に対する予測値を、predict()メソッドで予測。この結果は、1次元化されたf0やf1と同じく、2次元のmeshgridの各行を横に連ねたものになっている。

この結果を、meshgrid化されたf0(またはf1)と同じ形に変形。これで予測結果がf0×f1平面の各座標に対応した予測値の2次元配列となっている。

この結果を使い、contour()/contourf()で決定境界あるいは決定領域を描画。

ここでlevelsの指定は以下のようにしている。

まずcontour()の場合、ドキュメンテーションには“If an int n, use n data intervals; i.e. draw n+1 contour lines. The level heights are automatically chosen.”と書かれているので、levels=0と指定すると0+1本の線が描かれると考えたが以下のような警告が出て線の位置がずれた。

そこでlevels=[0.5]と2つのクラス値0と1の間をとると適切に表示される。

なおcontourf()のときは、levels=1として2つの領域が描かれる。

 

 

ndarray.min/max – 配列の最小値と最大値

ndarray.min()/max()は、配列の最小値/最大値を返すメソッド。また、ndarray.argmin()/argmax()は、最小/最大の要素のインデックスを配列で返す。

なお、numpy.amin()/amax()numpy.argmin()/argmax()もほぼ同じ動作をする。

以下、次の配列で動作を確認する。

引数に何も指定しない場合、配列の全要素の中の最小値と最大値を返す。このとき、argmin/argmaxでは、配列をreshape(-1)で1次元化したときのインデックスが返される。

引数にaxis=0を指定すると、各列ベクトルの行方向の中での最小値/最大値を返す。以下の例では、各列ごとの最小値/最大値とそれらに対する行インデックスが配列で返されている。引数との関係でいえば、axisが0番目のインデックス、すなわち行方向で探索した最小値/最大値を列ごとに返すということになる。

引数にaxis=1を指定すると、各行ベクトルの列方向の中での最小値/最大値を返す。以下の例では、各行ごとの最小値/最大値とそれらに対する列インデックスが配列で返されている。引数との関係でいえば、axisが1番目のインデックス、すなわち列方向に探索した最小値/最大値を行ごとに返すということになる。

 

pyplot – グラフ要素のフォントサイズ

グラフ全体のフォントサイズ

pyplot.rcParams()で基準のフォントサイズを変更。デフォルトはfont.size=12。以下は全体のフォントサイズを大きくした例。

個別要素のフォントサイズ

タイトル、軸ラベル、軸目盛、凡例について個別にフォントサイズを指定した例。

 

Python – 多重ループの一重化

概要

以下のような二重ループを、一重ループで実現する方法。

内包表記による方法

内包表記の中で二重ループを回し、1つのリストを生成する。

itertools.productによる方法

itertoolsライブラリーにあるproduct()は、引数のリストの各要素の直積を要素とするリストを返す。

 

numpy – r_とc_

概要

numpy.r_ / numpy.c_は配列を結合するオブジェクト。r_は縦方向に配列を結合し、c_は横方向に配列を結合する。vstack() / hstack()linspace()と似たような使い方ができるが、少し癖がある。

  • 配列と数値を混在させて結合できる
  • スライスでステップ数やか分割数を指定して数列をつくれる
  • vstack()hstack()の代わりに使える

vstack()hstack()と同じように使う。

r_について

numpy.r_で2次元配列に1行だけ追加するとき、1次元配列のままだ”次元が異なる”とエラー。素直にvstack()を使った方がよい。

r_のデフォルトで1次元配列同士を結合すると、単に横方向に結合される。配列と要素が混在していてもok。文字列の配列も結合できるが、文字列要素が混在するとエラーになる。

スライスを使って数列を生成。

3つ目の引数に'j'をつけてnumpy.linspace()と同様の動作。このときは終了値が含まれる。

c_について

numpy.c_で2次元配列にその行数と同じ要素数の1次元配列を結合すると、列ベクトルとみなされて1列追加される。hstack()が1次元配列を列ベクトル化する必要があるのに比べると手軽。

さらに要素数が同じ1次元配列同士を結合すると、それらが列ベクトルとみなされて結合される。

空の配列に対して順次列ベクトルを追加する場合には、empty(n, 0, dtype=type)を準備する。

 

numpy.percentile()~パーセンタイル

numpy.percentile()は、与えた配列から指定したパーセンタイル値を計算する。

percentile(a, q)
a:パーセンタイルを計算する元の配列。
q:パーセンタイル値、または配列。パーセンタイル値は0~100で、百分率表示であることに注意。1次元配列を指定すると、各要素のパーセンタイル値に相当する値が同じサイズの配列で返される。

以下は実行例。パーセンタイル値が要素の間になる場合は内挿される。

元の配列はソートされていなくてもよい。

 

パーセンタイル値を配列で指定した場合。

95%両側信頼区間の場合、以下のように計算できる。

 

ndarray – 整数の乱数配列を作る

重複しない乱数配列

0~n−1の整数を重複なくランダムに並べた配列。arange()で数列を作り、それをnumpy.randomモジュールのshuffle()permutation()でシャッフルする。shuffle()は元の配列を書き換え、permutation()は元の配列を書き換えずにシャッフル後の新たな配列を返す。permutation(n)で整数を指定すると、0 ~n-1がランダムに並んだ配列を返す。

“permutation”は置換の意味で、配列中の2要素を何回かランダムに置換していくイメージ(同じ単語が順列の意味でも使われる)。

m~n−1の乱数配列は、arange(m, n)をシャッフル。

重複を許す乱数配列

0~m−1の範囲で重複を許してn個の要素を持つ配列を生成する方法。

簡単なのはnumpy.randomchoice()でサイズを指定する方法。

m~n−1の範囲の乱数配列は、arange(m, n)choice()を使う。