reduce関数 シーケンスの値を累積的に集約する

Python2までは組込みでrudece関数というものがあったのですが、Python3ではfunctoolsという標準ライブラリの関数として提供されています。組み込み関数ではないのですが、map、filter、zip関数とともによく使用するため、合わせて紹介します。

reduce関数

reduce関数はリスト等のシーケンスの値を累積的に計算を行い1つの値に集約します。1番目の引数に、引数を2つ持つ関数を、2番目にリスト等のシーケンスを指定します。日本語の説明よりも、最初にサンプルを読んだほうがわかりやすいでしょう。以下は、1〜4までの和を求めるサンプルです。

from functools import reduce

def add(arg1, arg2):
    """ 2つの値を足して返す """
    return arg1 + arg2

x = reduce(add, [1, 2, 3, 4])
print(x) # 10

これはつまり、add(add(add(1, 2), 3), 4) = (((1 + 2) + 3) + 4) = 1 + 2 + 3 + 4 と同じことですね。時系列データ分析等、累積した前回の値を使用する計算でよく使用します。

補足 lambda式と組み合わせる

いつもの流れです。やはり上のような簡単な高階関数を使用する場合はlambdaを使用したほうが良いでしょう。

from functools import reduce

x = reduce(lambda x, y: x + y, [1, 2, 3, 4])
print(x) # 10

いつも通り、ずいぶんスッキリ書くことができました。

補足2 必ずしも両方の引数を使う必要はない

reduceの一番目の引数は、引数を2つもつ関数を指定しますが、前回の値から導出できる場合は2番目の引数を使わない場合もあります。例えば7%の金利で11年間複利で回した場合の計算は以下のようになります。0年始まりなので、要素数は12を指定しています。

from functools import reduce

def kinri(arg1, arg2):
    return arg1 + arg1 * 0.07

x = reduce(kinri, [100] * 12)
print(x)

7%複利を11年間回すと2倍になることが確認できます。(余談ですが金融業界ではこれをセブンイレブンの法則と呼んでいました。)

 
少々無理やりな説明でしたが、一部の引数を使わなくて済む場合もある、というわけです。