[解決!Python]累積和や累積積を求めるには:解決!Python
itertoolsモジュールのaccumulate関数やpandasのDataFrameオブジェクトが持つcumsumメソッドやcumprodメソッドで累積和や累積積を求める方法を紹介する。
l = [1, 2, 3, 4, 5]
result = [sum(l[:n+1]) for n in range(len(l))] # 累積和を求める
print(result) # [1, 3, 6, 10, 15]
from itertools import accumulate
result = accumulate(l) # accumulate()の戻り値はイテレータ
print(result) # <itertools.accumulate object at 0x109fc9df0>
for n in result:
print(n)
# 出力結果:
#1
#3
#6
#10
#15
result = accumulate(l)
mylist = list(result) # イテレータをリストに変換
print(mylist) # [1, 3, 6, 10, 15]
# functionパラメーターに関数を渡すと累積和以外の計算も可能
result = accumulate(l, lambda x, y: x * y) # 累積積を計算
print(list(result)) # [1, 2, 6, 24, 120]
# 上と同じことをoperatorモジュールを使って記述する
import operator
result = accumulate(l, operator.mul) # 累積積を計算
print(list(result)) # [1, 2, 6, 24, 120]
# initialパラメーターに初期値を指定
result = accumulate(l, initial=100) # 初期値100にリストの内容を累積的に加算していく
print(list(result)) # [100, 101, 103, 106, 110, 115]
import pandas as pd
s = pd.Series(l)
print(s)
# 出力結果:
#0 1
#1 2
#2 3
#3 4
#4 5
#dtype: int64
result = s.cumsum() # pandasのSeries.cumsumメソッドでも同様の処理が可能
print(result)
# 出力結果:
#0 1
#1 3
#2 6
#3 10
#4 15
#dtype: int64
df = pd.DataFrame([[1, 2], [3, 4], [5, 6]])
result = df.cumsum() # DataFrameのcumsumメソッドで列ごとに累積和を計算
print(result)
# 出力結果:
# 0 1
#0 1 2
#1 4 6
#2 9 12
result = df.cumsum(axis=1) # axis=1を指定すると行ごとに累積和を計算
print(result)
# 出力結果:
# 0 1
#0 1 3
#1 3 7
#2 5 11
# DataFrame.cumprodメソッドは累積積を計算
result = df.cumprod()
print(result)
# 出力結果:
# 0 1
#0 1 2
#1 3 8
#2 15 48
累積和を求める
累積和とはリストなどの要素を順番に加算していった結果のことだ。例えば、[1, 2, 3, 4, 5]というリストがあったとき、その累積和は次のようになる。
累積和は次のようにして計算できる。ここではリスト内包表記の中で元となるリストのスライスの和を求めるようにしている。
l = [1, 2, 3, 4, 5]
result = [sum(l[:n+1]) for n in range(len(l))] # 累積和を求める
print(result) # [1, 3, 6, 10, 15]
このようにしても累積和は求められるが、itertoolsモジュールにはこれを計算するaccumulate関数が用意されている。ただし、この関数はリストを返すのではなく、イテレータを返す点には注意すること。以下にaccumulate関数の使用例を示す。
from itertools import accumulate
result = accumulate(l) # accumulate()の戻り値はイテレータ
print(result) # <itertools.accumulate object at 0x109fc9df0>
for n in result:
print(n)
# 出力結果:
#1
#3
#6
#10
#15
accumulate関数の戻り値からリストを得るには、list関数に(使い果たす前の)イテレータを渡せばよい。
result = accumulate(l) # イテレータを使い果たしているので再作成
mylist = list(result) # イテレータをリストに変換
print(mylist) # [1, 3, 6, 10, 15]
また、accumulate関数のfunctionパラメーターに関数を渡すと、その関数を使って初期値より後の要素が計算される。この関数は2つの引数を取る関数である必要があり、そのうちの1つ(第0引数)は累積された値を、もう1つ(第1引数)は累積された値に適用する値となる。
例を以下に示す。
result = accumulate(l, lambda x, y: x * y) # 累積積を計算
print(list(result)) # [1, 2, 6, 24, 120]
この例では2つの引数の積を求めるラムダ式をfunctionパラメーターに指定しているので、結果的には累積積が求められる。
ラムダ式の代わりにoperatorモジュールが提供する、Pythonの演算子に対応する関数を指定してもよい。以下ではoperator.mul関数を使う例だ。
import operator
result = accumulate(l, operator.mul) # 累積積を計算
print(list(result)) # [1, 2, 6, 24, 120]
accumulate関数のinitialパラメーターには累積計算する際の初期値を指定できる。例えば、初期値を100として、それに[1, 2, 3, 4, 5]というリストの要素を累積的に加算するなら次のようなコードとなる。
result = accumulate(l, initial=100) # 初期値100にリストの内容を累積的に加算していく
print(list(result)) # [100, 101, 103, 106, 110, 115]
なお、pandasのDataFrameオブジェクトとSeriesオブジェクトでは累積和を計算するcumsumメソッドと累積積を計算するcumprodメソッドがある。pandasを使うコードを書いているのであれば、これらを使ってもよいだろう。
以下に例を示す。
import pandas as pd
s = pd.Series(l)
print(s)
# 出力結果:
#0 1
#1 2
#2 3
#3 4
#4 5
#dtype: int64
result = s.cumsum() # pandasのSeries.cumsumメソッドでも同様の処理が可能
print(result)
# 出力結果:
#0 1
#1 3
#2 6
#3 10
#4 15
#dtype: int64
df = pd.DataFrame([[1, 2], [3, 4], [5, 6]])
result = df.cumsum() # DataFrameのcumsumメソッドで列ごとに累積和を計算
print(result)
# 出力結果:
# 0 1
#0 1 2
#1 4 6
#2 9 12
result = df.cumsum(axis=1) # axis=1を指定すると行ごとに累積和を計算
print(result)
# 出力結果:
# 0 1
#0 1 3
#1 3 7
#2 5 11
# DataFrame.cumprodメソッドは累積積を計算
result = df.cumprod()
print(result)
# 出力結果:
# 0 1
#0 1 2
#1 3 8
#2 15 48
DataFrame.cumsumメソッドやDataFrame.cumprodメソッドではaxisパラメーターを指定しない(もしくは0を指定する)と列ごとに累積和や累積積を、axisパラメーターに1を指定することで行ごとに累積和や累積積を計算できる。
Copyright© Digital Advantage Corp. All Rights Reserved.