Python – 行・列単位の合計・率の計算

概要

2次元のndarrayDataFrameで、行単位や列単位での合計を計算したり、それを使って行単位/列単位の率を計算する方法。

2次元のndarrayの場合は、

  • 合計はsum()メソッドの引数にaxisを指定
    • 列和ならaxis=0、行和ならaxis=1
    • 結果は1次元配列で得られる
  • 率の計算はこれらの合計の配列を使うが、列和に対する各列要素の率なら1次元配列の行ベクトルのまま、行和に対する各行要素の率なら2次元の列ベクトルに変換して除算

DataFrameの場合、まず合計を求めるには、

  • 合計はsum()メソッドの引数にaxisを指定
    • 列和ならaxis=0、行和ならaxis=1
    • 結果はSeriesオブジェクトで得られる

その上で率の計算には2通りある。1つ目はSeriesオブジェクトの内容をndarrayとして取り出して計算する方法で、

  • Series.valuesで列和/行和の配列を取り出し、ndarrayの場合と同じ方法で計算する

もう1つの方法はSeriesオブジェクトのままでdiv()メソッドにaxisを指定する方法で、

  • 列和に対する各列要素の率を計算するには、div(列和Series, axis=1)
  • 行和に対する各行要素の率を計算するには、div(列和Series, axis=0)

ndarrayの場合

確認

まず確認のために、以下の配列を準備する。

行ベクトルを2次元配列に加えると、配列の各行に対して行ベクトルが加えらえる。

列ベクトルを2次元配列に加えると、配列の各列に対して列ベクトルが加えられる。

つまり、ndarrayの2次元配列に行または列のベクトルを加えると、加える方のベクトルの形状に合わせて各行/列に演算が実行される。これは他のオペレーターについても同じ。

この演算は直感的にも分かりやすく、列ごと/行ごとの小計に対する比率の計算も思い浮かべることができる。

合計

ndarrayの各列/行に沿った合計を計算する。合計計算はndarraysum()メソッドを使うが、引数を省略すると全要素の和となる。引数にaxis=0を指定すると列方向に処理がされ(つまり配列の各列の要素が列方向に足され)、axis=1を指定すると行方向に処理がされる(つまり配列の各行の要素が行方向に足される)。

以下の例は、最初に使った2次元配列の列方向の和(の行ベクトル)と行方向の和(の列ベクトル)を計算している。

率の計算

2次元配列を行合計ベクトルで割ると、各行の要素が合計ベクトルの各要素で割られる(各列の行要素の合計は1になる)。

また、2次元配列を列合計ベクトルで割ると、各列の要素が合計ベクトルの各要素で割られる。繰り返しになるが、この場合の合計ベクトルは2次元の列ベクトルになっている。

以下の図のように、この

DataFrameの場合

確認

まず確認のために、以下のDataFrameSeriesを準備する。2次元配列はndarrayの例と同じものを流用。

合計ベクトルがndarrayの場合

演算をほどこすベクトルがndarrayの場合、2次元配列の時と同じように、ベクトルが行/列によって自動的に加えられる方向が決められる。

合計ベクトルがSeriesの場合

DataFramesum()メソッドで行や列の合計を計算するとSeriesオブジェクトで結果が得られるため、その挙動を確認しておく。

Seriesを単純にDataFrameと演算子で結ぶと、行ベクトルとして扱われる。

Seriesは行・列の概念を持たないが、演算の方向を明示するのに以下の方法をとる。

演算子に対応するメソッドは、addsubmuldivmodpowが準備されている。

合計

列/行ごとの合計は、ndarrayと同じくDataFramesum()メソッドで引数axisを指定して計算する。

 

率の計算

Seriesndarrayで取り出して計算する方法

Seriesvaluesプロパティーでその内容をndarrayとして取り出せる。

列和に対しては、それを行ベクトルのまま除算すれば、各列の要素を行ベクトルの対応する要素で割った値となる。

行和に対しては、ndarrayを1列の列ベクトルに変換して除算すれば、各行の要素を列ベクトルの対応する要素で割った値となる。

Seriesのままで計算する方法

合計Seriesをそのまま使って除算する場合はDataFramediv()メソッドを使いaxisを指定するが、axisの指定の仕方に注意が必要。

列和で除算する場合は、その各要素が各行の各要素に対応するため、列和を行ベクトルとみて各行に除算を適用する(axis=1)。

分かりにくいので図示すると以下のようになる。まず合計を求めるのにsum()メソッドでaxis=0として列和を求める。この合計で各要素を割るのに1列目の要素は合計の1つ目の要素、2列目の要素は合計の2つ目の要素・・・で割る必要があるので、div()メソッドでaxis=1とする。こうすると合計のSeriesは行ベクトルとみなされて、それが各行の要素に適用される。

行和で除算する場合は、その各要素が各列の各要素に対応するため、行和を列ベクトルとみて各列に除算を適用する(axis=0)

これも分かりにくいので以下のように図示する。合計を求めるのにsum()メソッドでaxis=1として行和を求める。この合計で各要素を割るのに1行目の要素は合計の1つ目の要素、2行目の要素は合計の2つ目の要素・・・で割る必要があるので、div()メソッドでaxis=1とする。こうすると合計のSeriesは列ベクトルとみなされて、それが各列の要素に適用される。

このように、div()のような演算子メソッドでaxisを使う方法はややこしい(少なくとも私には)。

実行速度

各計算方法の実行速度には、あまり大きな差は出なかった。

実行時間は以下の通りで、各計算手法の間に差はない。敢えて言えば、DataFrameを使った場合に僅かに時間がかかっている。

なお、この計算はpandasのバージョン1.1.4で実行したが、upgrade前のバージョン0では、3つ目と5つ目、DataFrameで行単位の演算を行うときに20秒台と2桁長い時間がかかっていた。

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です