パンダのデータフレームを簡単にフィルタリングするためのラムダ関数を含む辞書を作成したいと思います。各辞書アイテムを1行ずつインスタンス化すると、希望する動作が得られます。しかし、forループを使用すると、フィルターは最後の値nを使用します。ラムダ関数は、インスタンス化時の値ではなく、グローバル変数nを参照しますか?ラムダ関数についての私の理解はずれていますか?
この例は骨抜きになっていることに注意してください。私の実際のプロジェクトでは、DateTimeインデックスを使用しており、辞書には年でフィルタリングする整数キーがあります。df.index.year == 2020
、および週/週末、時刻などでフィルタリングするいくつかの文字列キー。
import pandas as pd
data = [[1,2],[3,4],[5,6]] # example df
df = pd.DataFrame(index=range(len(data)), data=data)
filts = {}
filts[1] = lambda df: df[df.index == 1] # making a filter dictionary
filts[2] = lambda df: df[df.index == 2] # of lamda funcs
print(filts[1](df)) # works as expected
print(filts[2](df))
filts = {}
for n in range(len(data)):
filts[n] = lambda df: df[df.index == n] # also tried wrapping n in int
# n = 0 # changes behaviour
print(filts[0](df)) # print out the results for n = 2
print(filts[1](df)) # same problem as above
# futher investigating lambdas
filts = {}
n = 0
filts[n] = lambda df: df[df.index == n] # making a filter dictionary
n = 1
filts[n] = lambda df: df[df.index == n] # of lamda funcs
print(filts[0](df)) # print out the results for n = 1
質問の重複性についてはよくわかりませんが、パンダを使ってこれに遭遇したので、答えています。クロージャーを使用して問題を解決できます。
次のようにループを変更します。
for n in range(len(data)):
filts[n] = (lambda n: lambda df: df[df.index == n])(n)
OPのアプローチの何が問題になっていますか?
ラムダは変数への参照を維持します。したがって、これn
はループ内で繰り返されている変数への参照です。ラムダを評価するとき、n
(で定義されているすべてのラムダで、ループ内filts
の参照n
に割り当てられた最終値に割り当てられます。したがって、表示されているものが期待されます。要点- 「ラムダのクロージャは使用されている変数への参照であり、その値ではないため、後で変数の値が変更されると、クロージャの値も変更されます。 " source。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加