今回は、複数のpandasオブジェクト同士の算術における動作について学んでいく。

シリーズの加算

まずは簡単な例として、シリーズを加算した例を見てみよう。

import pandas as pd
import numpy as np

series1 = pd.Series([-2.5, 5.3, -1.9, 3.2], index=['a', 'b', 'c', 'd'])
# a   -2.5
# b    5.3
# c   -1.9
# d    3.2
# dtype: float64

series2 = pd.Series([8.5, -1.2, -0.1, 4.5, 2.8], index=['b', 'a', 'c', 'e', 'f'])
# b    8.5
# a   -1.2
# c   -0.1
# e    4.5
# f    2.8
# dtype: float64

series1 + series2
# a    -3.7
# b    13.8
# c    -2.0
# d     NaN
# e     NaN
# f     NaN
# dtype: float64

二つのオブジェクト(シリーズ)を加算すると、インデックスが重複したもの同士を足し合わせ、重複しないインデックスには欠損値が代入される。

データフレームの加算

データフレームの加算では次のとおり、計算は行列に対して行われる。
欠損値代入の動作はシリーズの場合と変わらない。

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.arange(15.).reshape(3, 5), index=['Tokyo', 'Osaka', 'Nagoya'], columns=list('abcde'))
df2 = pd.DataFrame(np.arange(20.).reshape(4, 5), index=['Osaka', 'Nagoya', 'Tokyo', 'Fukuoka'], columns=list('cdaef'))

df1 + df2
#             a   b     c     d     e   f
# Fukuoka   NaN NaN   NaN   NaN   NaN NaN
# Nagoya   17.0 NaN  17.0  19.0  22.0 NaN
# Osaka     7.0 NaN   7.0   9.0  12.0 NaN
# Tokyo    12.0 NaN  12.0  14.0  17.0 NaN

pandasオブジェクトの算術メソッド

一方にしかインデックスが無い場合、先述の例のとおり欠損値が代入されるが、任意の値による計算をおこないたい場合もあるだろう。

算術メソッドのaddを使えば、引数fill_valueに指定した値を使って計算をおこなうことができる。

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.arange(15.).reshape(3, 5), index=['Tokyo', 'Osaka', 'Nagoya'], columns=list('abcde'))
df2 = pd.DataFrame(np.arange(20.).reshape(4, 5), index=['Osaka', 'Nagoya', 'Tokyo', 'Fukuoka'], columns=list('cdaef'))

df1.add(df2, fill_value=0)
#             a     b     c     d     e     f
# Fukuoka  17.0   NaN  15.0  16.0  18.0  19.0
# Nagoya   17.0  11.0  17.0  19.0  22.0   9.0
# Osaka     7.0   6.0   7.0   9.0  12.0   4.0
# Tokyo    12.0   1.0  12.0  14.0  17.0  14.0

加算の他、減算などのその他算術メソッドも当然用意されているので、下記にまとめておく。

メソッド説明
add加算 (+)
sub減算 (-)
mul乗算 (*)
div除算 (/)
pow累乗 (**)

データフレームとシリーズの演算

データフレームとシリーズのように、次元が違うオブジェクト同士の演算をおこなうことも可能だ。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(15).reshape(3, 5))
#     0   1   2   3   4
# 0   0   1   2   3   4
# 1   5   6   7   8   9
# 2  10  11  12  13  14

series = pd.Series(np.arange(5))
# 0    0
# 1    1
# 2    2
# 3    3
# 4    4
# dtype: int64

df.sub(series)
#     0   1   2   3   4
# 0   0   0   0   0   0
# 1   5   5   5   5   5
# 2  10  10  10  10  10

これはデータフレームとシリーズを、subメソッドを使って減算した例だが、データフレームの各行に対してシリーズの値が減算されていることが分かる。

この各行へ対しておこなわれる処理をブロードキャストと言う。

ブロードキャストはデフォルトでは、シリーズのインデックスと、データフレームの列がマッチングされ演算が行われるが、データフレームの行(インデックス)にマッチングさせたい場合があるだろう。

その場合は、算術メソッドの引数axisでマッチさせたい軸を指定すれば良い。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(15).reshape(3, 5))
#     0   1   2   3   4
# 0   0   1   2   3   4
# 1   5   6   7   8   9
# 2  10  11  12  13  14

series = pd.Series(np.arange(5))
# 0    0
# 1    1
# 2    2
# 3    3
# 4    4
# dtype: int64

df.sub(series, axis=0)
#      0    1     2     3     4
# 0  0.0  1.0   2.0   3.0   4.0
# 1  4.0  5.0   6.0   7.0   8.0
# 2  8.0  9.0  10.0  11.0  12.0
# 3  NaN  NaN   NaN   NaN   NaN
# 4  NaN  NaN   NaN   NaN   NaN