Python – 平均・分散・共分散

1次元配列の場合

平均

平均はmean()メソッドで計算。

分散・標準偏差

標本分散・標本標準偏差

分散はvar()メソッド、標準偏差はstd()メソッドで計算。デフォルトでは標本分散と標本標準偏差。

不偏推定量

分散の算出では、引数ddof (delta degrees of freedom)で指定した引数をデータ数nから引いた数で偏差の二乗和を割る。デフォルトではddof=0なので標本分散、標本標準偏差になるが、ddof=1を指定すると、不偏分散、標準偏差の不偏推定量が計算される。

2次元配列の場合

平均

平均はmean()メソッドで計算。引数axis=0/1で列方向/行方向の計算方向を指定。計算結果は1次元配列で、要素数は列方向の平均なら行数、行方向の平均なら列数と同じになる。

分散・標準偏差

標本分散・標本標準偏差

分散はvar()メソッド、標準偏差はstd()メソッドで計算。デフォルトでは標本分散、標本標準偏差を計算。デフォルトでは標本分散、標本標準偏差。

不偏推定量

引数ddof=1を指定すると、データ数nからddof=1を引いた数で偏差の二乗和が割られ、不偏分散、標準偏差の不偏推定量が計算される。

共分散

cov()メソッドで二つのデータの共分散行列を計算する。結果は2次元配列で得られ、対角要素は各データの分散、対角要素以外の要素は行数・列数に対応する共分散。

デフォルトでは引数bias=Falseとなっていて、偏差の積和をn−1で割った不偏推定量が計算される。

bias=Trueを指定すると、偏差の積和を割る数がnとなり、標本に対する分散・共分散が計算される。

 

axisの方向

概要

配列などのメソッドの引数で指定するaxis=0/1について確認。

  • axis=0は配列やDataFrameを列単位で捉えて、その列の中で処理を行いながら、すべての列に対して処理が行われる
    • SerieseオブジェクトがDataFrameの処理の対象となる場合は列として扱われ、DataFrameの各列を処理しながらすべての列に適用される
  • axis=1は配列やDataFrameを行単位で捉えて、その行の中で処理を行いながら、すべての行に対して処理が行われる。
    • SerieseオブジェクトがDataFrameの処理の対象となる場合は行として扱われ、DataFrameの各行を処理しながらすべての行に適用される

ndarrayの場合

まずndarrayの2次元配列で確認する。

max()メソッド

  • axis=0は列単位で各列の最大値を探し、それらを要素とする配列(要素数=列数の1次元配列)
  • axis=1は行単位で各行の最大値を探し、それらを要素とする配列(要素数=行数の1次元配列)

sum()メソッド

  • axis=0は列単位で各列の合計を要素とする配列(要素数=列数の1次元配列)
  • axis=1は行単位で各行の合計を要素とする配列(要素数=行数の1次元配列)

repeat()メソッド

  • axis=0は列単位で各列の要素が指定回数繰り返される
  • axis=1は行単位で各行の要素が指定回数繰り返される

図による理解

sum()メソッドを例に、axis=0/1に対する挙動を図にすると、以下のようになる。

DataFrameの場合

以下のDataFrameSeriesオブジェクトで確認する。Seriesオブジェクトは行として扱われ、array_like、1次元の配列でも同じ結果になる。

min()メソッドなど

minmaxsumなどのメソッドの考え方はndarrayと同じ挙動。

add()などの演算メソッド

DataFrameには演算子による演算の代替となるメソッドがある(addsubmuldivmodpow)。addメソッドを例にとると、以下のように引数を指定。

add(array_like, axis=0/1)

  • axis=0array_likeを列とみなして、DataFrameオブジェクトの各列の要素との和を計算する
  • axis=1array_likeを行とみなして、DataFrameオブジェクトの各行の要素との和を計算する

apply()メソッド

applyメソッドは、行または列を指定した関数に渡す。

  • axis=0DataFrameオブジェクトの各列を指定した関数に渡す
  • axis=1DataFrameオブジェクトの各行を指定した関数に渡す

演算メソッドの図による理解

演算メソッドは少し挙動が違うので図で整理しておく。1次元のarray_likeオブジェクトがaxisの指定によって列/行としてみなされる点に注意。

補足

1次元配列の場合

1次元配列に対してaxis引数を使う場合、行ベクトルとしてaxis=1に反応しそうだが、実際にはaxis=0で各要素に対する処理が行われる。axis=1を指定すると、たとえば以下のようなエラーになる。

元々多次元配列を意図した引数なので、1次元配列に使うのはナンセンスだろう(axis=0を行単位の処理にしておけば自然ではあったかもしれないが)。

1行の2次元配列の場合

1行の配列(1つの1次元配列を要素に持つ2次元配列:行ベクトル)に対するaxisの効果を、sumメソッドで見てみる。

axis=0の場合は各要素が1要素の列ベクトルとみなされ、3つの列(要素)ごとに処理される。その結果は3つの要素を持つ1次元配列(行ベクトル)となる。

axis=1の場合は行ベクトル全体が1つの行とみなされ、それらの要素に対して処理がされる。その結果は1つの数値となるが、1つの要素を持つ1次元配列で返される。

1列の2次元配列の場合

1列の配列(列ベクトル)に対するaxisの効果を、sumメソッドで見てみる。

axis=0の場合は3つの要素を持つ1つの列に対して処理される。その結果は1つの数値となるが、1つの要素を持つ1次元配列で返される。

axis=1の場合は列の各要素が1要素の行とみなされ、3つの行(要素)ごとに処理される。その結果は3つの要素を持つ列ベクトルだが、3つの要素を持つ1次元配列(行ベクトル)で返される。

DataFrame – 列の操作

概要

DataFrameの列の操作をまとめる。

以下、次のDataFrameを使う。

列の参照

DataFrameで列名を直接指定

1つの列を指定

DataFrameで直接列名を指定するとSeriesオブジェクトが得られ、リストやndarrayにも変換できる。

ファンシー・インデックスによる複数列の指定

DataFrameで直接列名を指定する際に列名のリストを渡すと、その要素の列が並んだDataFrameが返される。

locによる列の指定

1つの列の指定

locで全行のスライス':'とすることで、列名を指定して列を取り出すことができる。結果はSeriesオブジェクト。

スライスによる連続した列の指定

列名にもスライスを使って連続した列を参照することができ、複数列の場合はDataFrameが返される。

ファンシーインデックスによる複数列の指定

locでもファンシーインデックスを使うことができて、個別の列を組み合わせたDataFrameを得ることができる。

列の追加

DataFrameで直接列名を指定して追加

DataFrameに新たな列名を指定して末尾に列を追加。列にarray_likeではなく数値を指定すると、列の全ての要素が同じ数値で埋められる。

locでスライス指定して追加

全行をスライス指定、新たな行名を指定して末尾に列を追加。

assignメソッドによる追加

assignメソッドで末尾に追加する場合、列名は文字列("列名")ではなく、直接「列名=列」で指定する。assignメソッドは元のオブジェクトは変更せず、新たなDataFrameを生成して返す。

insertメソッドによる途中への追加

insertメソッドは(挿入する列位置、"列名"、挿入する列)で挿入する。

列の更新

DataFrameで列名を直接指定

1つの列を指定

DataFrameで列名を直接指定して、その列に新たな列を代入する。代入する列は縦ベクトルでなくてもよく、1次元のリストや配列でよい。

ファンシーインデックスによる複数列の指定

ファンシーインデックスで複数列をリストで指定し、その列数と同じ列数のデータを与えて更新する。

locによる列名・スライスの指定

1つの列の指定

locで全行のスライスと1つの列名を指定して列を更新。

スライスによる連続した列の指定

スライスで連続した列を指定して一括して更新することができる。その場合、指定されたDataFrameの形状に合った次元・次数のデータを与える必要がある。

ファンシーインデックスによる複数列の指定

ファンシーインデックスも使うことができて、この場合も形状に合った次元・次数のデータを与える必要がある。

列の削除

例題のデータ

以下の2つのデータを使って、列番号指定の場合と列名指定の場合を確認する。

1列の削除

drop()メソッドの引数に削除する列の列番号とaxis=1を指定して削除(axis指定の方向に注意)。

第1引数の列指定はlabels=1labels="one"のように指定してもよい。

複数列の削除

複数列を削除する場合はリストで指定。

連続した列の削除

連続した列を削除する場合はリストの内包表記で。

文字列の列名の場合は、泥臭いが以下の方法か。

 

DataFrame – 要素の内容の参照・変更

要素の操作

以下の2つのDataFrameを使っていく。

at/iat~単独要素の参照・変更

at~インデックス指定

atは行・列のラベルを指定して単独の要素を参照・変更

インデックスがデフォルトの数値の場合は数値指定。

iat~行・列番号指定

iatは行・列の番号を数値で指定して単独の要素を参照・変更。行・列のインデックスはカウントされない。

インデックスがデフォルトの数値の場合は数値指定。

loc/iloc~単独要素・スライスの参照・変更

loc~インデックス指定/終端含む

locの単独要素指定もatと同様。

locは行・列のラベルにスライスを指定可能。ただしlocのスライス指定ではリストや配列と異なり、(デフォルトの数値ラベルであっても)終端の行・列を含む点に注意

スライス指定した範囲を変更可能。行単位・列単位のデータの更新の際に使う。

iloc~行・列番号指定/終端含まず

ilocは行・列の番号にスライスを指定可能。ilocのスライス指定では、リストや配列と同じで、終端の行・列は含まれない

ilocでもスライス指定で内容変更が可能。

DataFrame – 生成時の数値と文字列の混在について

概要

DataFrameは列同士の型が異なってもよいが、配列でデータを組み立てる場合に数値と文字を混在させると、数値が全て文字列となってしまうので注意が必要。

配列は不適

以下のようにndarrayで文字列と数値を混在させたデータを基にしてDataFrameを生成すると、その内容が全て文字列になってしまう。

このデータの数値演算を行おうとすると以下のように文字列演算になってしまう。

これはndarrayが型の混在を許さないためで、いわばケアレスミスだが注意。

リストはOK

元のデータをリストにすれば問題なく数値と文字列に分けられる。

列の辞書もOK

列ごとのリストを辞書で組み立てても数値と文字は分けられる。

 

DataFrame – 生成

リスト・配列からの生成

リストからの生成

2次元のリストをそのまま引数にしてDataFrameを生成。列名・行名には自動的に番号が振られる。

ndarrayからの生成

2次元のndarrayからもDataFrameを生成可能。

列名・行インデックスの設定

DataFrame生成時にcolumnsで列名を、indexで行インデックスを設定可能。

列リストと辞書による

列ごとのリストやndarrayが与えられていれば、それぞれの列名をキー、リストや配列を値とした辞書を引数にしてDataFrameを生成できる。

 

DataFrame – 情報・内容の取得

概要

pandas.DataFrameの行数・列数などの数や、列名・行名・データ配列を取り出す方法。以下のデータを使う。

行数・列数・サイズ

df.shapeプロパティーで(行数, 列数)のタプルが帰る。2つの変数にアンパッキングして使える。列名やインデックス列は行数・列数にカウントされない。

行数だけを得るにはlen(df)、列数だけを得るにはlen(df.columns)

df.sizeで全要素数を得られる。

行名・インデックス・データの内容

列名~columns

列名はcolumnsプロパティーで得られる。Indexオブジェクトで格納されていて、リストやndarrayにも変換可能。

行名~index

列名はcolumnsプロパティーで得られる。こちらもIndexオブジェクトで格納されていて、リストやndarrayにも変換可能。

データの内容~values

列名・行名を除いたデータの内容のみを取り出したいときはvaluesプロパティーにアクセスする。結果はndarrayで返される。

なお、valuesの内容を変更すると元のデータが変更される点に注意。以下は元データをndarrayで与えているが、リストで与えても結果は同じ。

 

Figure全体のタイトル

複数グラフを含むFigure全体に1つのタイトルを付けたい場合、Figure.suptitle()を使う。

 

Axesで軸を反転させる

軸の反転には、invert_xaxis()invert_yaxis()を使う。

軸が反転されているかどうかの確認には、xaxis_inverted()yaxis_inverted()を使う。

 

実行結果

 

sklearn – confusion_matrix

概要

機械学習の精度を複数の視点で確認するのに、Confusion Matrix(混同行列)を用いるが、sklearn.metricsパッケージのconfusion_matrixモジュールはこの集計を自動で行ってくれる。

使い方

引数

confusion_matrix(y_true, y_pred, labels=None, normalize=None)

y_true
ターゲットの正解の配列を与える。
y_pred
予測されたターゲットの配列を与える。
labels
表示される順番を変更したいときに、ターゲット値をリストで指定する。
normalize
合計値に対する比率で表示する。正解の合計に対する場合は'true'、予測結果の合計に対する場合は'pred'、全体の合計に対する場合は'all'を指定する。

戻り値

戻り値は[n_class, n_class]の2次元配列で、各行が正解の各クラス、各列が予測された各クラスに対応する。各クラスの並びは、数値なら昇順、文字列なら辞書順で、行・列とも同じ並びになる。

実行例

データの準備とモデルによる予測

Breast Cancerデータセットで使い方を見ていく。まず、cancerデータを読み込み、訓練データとテストデータに分割する。予測モデルにはLogistic回帰を用いて、訓練データについてターゲットを予測する。以降、訓練データに関する正解ターゲットと予測ターゲットを使う。

ここでデータの内容を確認しておく。正解データ、予測データとも0/1の2クラスで、0が悪性(malignant)、1が良性(begnign)と定義されている。

また、0/1の数値によるクラス表現を文字列表現にした配列を別に作っておく。

基本的な使い方

要素のみを得る

基本的な使い方は、confusion_matrix()の引数に正解データと予測データをコレクションで与える。結果は行・列とも昇順で並べられる。以下の例では、1行目が正解・悪性、2行目が正解・良性、1列目が予測・悪性、2列目が予測・良性となっている。

クラスが文字列で表現されている場合は、文字列の辞書順なので、行・列とも'benign''malignant'の順で並べられる。この結果、数値表現の場合に対して行・列とも入れ替わっている。

要素の並び順を変更する

引数labelsにリストでクラスの並びを指定できる。以下の例ではデフォルトの昇順の並びを変更している。

要素を正規化する~比率で表す

引数normalizeで合計に対する比率の計算の仕方を指定できる。

normalize='true'の場合、正解の各行の合計に対する比率が計算される。以下の例では行の合計で各要素が除され、各行の合計が1となっている。

normalize='pred'の場合、予測の各列の合計に対する比率が計算される。以下の例では列の合計で各要素が除され、各列の合計が1となっている。

normalize='all'の場合、すべての要素の合計に対する比率が計算される。以下の例では、全要素の合計が1となっている。

なお、normalize='all'を指定した場合の対角要素の和は、全要素に対する正解要素の比率になり、score()メソッドの値と等しい。

DataFrameによる扱い

ラベルの追加

pandasDataFrameを使うと、行・列のラベルが表示されるので見やすくなる。行(正解)のラベルはindexで、列(予測)のラベルはcolumnsで指定し、同じ内容のコレクションを与える。

合計欄

DataFramesum()メソッドで、行・列の合計を計算して追加すると見やすい。sum()メソッドの引数を省略するとデフォルトのaxis=0となり、列ごとの合計が1次元配列で得られる。引数をaxis=1とすると行単位の合計が1次元配列で得られる。

以下の例では、まず列方向の合計(各予測クラスの合計)を最後の行に加え、その行も含めて行方向の合計(各正解クラス、予測クラス合計の合計)を最後の列に加える。

Multiindex

DataFrameのMultiindexを使うと、正解・予測を表示できるのでより分かりやすくなる。ただし行・列・要素の指定が少し煩雑になる。

以下はMultiindexの場合に合計欄を加える例。